[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Sobre Bash
- To: mindfood@xxxxxxxxxxxxxxx
- Subject: Sobre Bash
- From: Jose San Leandro <jose.sanleandro@xxxxxxxxxxxx>
- Date: Thu, 14 Feb 2008 10:14:04 +0100
- Delivered-to: mailing list mindfood@orange-soft.com
- Delivered-to: moderator for mindfood@orange-soft.com
- Mailing-list: contact mindfood-help@orange-soft.com; run by ezmlm
- Organization: Ventura24
- User-agent: KMail/1.9.7
Hola a todos,
Hace tiempo que no nos molestamos en activar esta lista de correo. Voy a
aprovechar para comentar impresiones y opiniones a raiz de un esfuerzo que he
hecho para uniformizar y mejorar la calidad general de los scripts Bash en la
empresa para la que trabajo.
Generalmente, los shell-scripts son mini-programas poco estructurados que
sirven para un propósito concreto. A medida que aumentan en complejidad
suelen ser reescritos en lenguajes compilados o de más alto nivel.
Es cierto que los tipos de datos en Bash son muy escasos (strings, numéricos y
arrays), y que las estructuras de control son demasiado sensibles a aparentes
trivilalidades como retornos de carro o espacios. Sin embargo, considero que
cuando se opta por Bash, se debería dedicar algo de esfuerzo para hacer que
los scripts tengan una mínima calidad: que estén estructurados, que permitan
una opción para saber qué hacen (típicamente -h o --help), que se aseguren de
borrar los ficheros temporales que utilicen, etc.
Con ese objetivo, y para consolidar los scripts en la organización (algunos
son bastante críticos), he estado investigando y finalmente he optado por una
solución: utilizar un script genérico "heredado" por todos los demás, en el
que se ofrezcan automáticamente ciertas características deseables.
Para ello, basta con cambiar la primera linea del script, que suele ser
#!/bin/bash o #!/bin/sh por #!/bin/bash /ruta/del/script/comun. De esta forma,
lo que en realidad se ejecuta es siempre el script "padre", y bash le añade
como primer argumento la ruta del script original. Con este mecanismo el
script padre tiene el control, y puede realizar ciertas comprobaciones y
dotar al script hijo de lógica adicional.
En la actualidad, las características que he implementado son:
- Gestión de parámetros y flags: no uso getopts porque no me permite utilizar
flags en formato largo y corto. He implementado funciones que realizan la
misma lógica que getopts. He incluído por defecto el soporte para los
flags -v, -vv, -vvv y -h|--help.
- Gestión de errores: El script hijo debe definir constantes para los posibles
errores, y de esa forma la ejecución puede terminar abruptamente y ofrecer al
usuario un código de error diferenciado. Dichos códigos se generan
secuencialmente, y se pueden consultar ejecutando el script con las
opciones -vvv -h.
- Gestión de variables de entorno: El script hijo puede delegar en variables
de entorno los valores de ciertos parámetros, y utilizar valores por defecto
si tales variables no están definidas. También se documentan automáticamente
con las opciones -vvv -h.
- Gestión de dependencias: El script hijo define qué utilidades requiere que
estén instaladas, y el script padre se encarga de verificar que están
disponibles en una etapa temprana.
- Funciones de propósito general: desde creación de ficheros temporales (con
mktemp) a lógica de fechas (un infierno en bash).
- Soporte para interrupción inesperada. Ante una señal de interrupción (como
ctrl-c), el script llamará a una función concreta, que por ejemplo tiene en
cuenta cualquier fichero temporal creado para así borrarlo. El script hijo no
tiene que preocuparse, tiene un garbage collector de los ficheros temporales
que utilice.
Otras ideas que pensaré en incluir más adelante serían:
- Comprobación de versión y actualización automática del script padre desde
Subversion.
- Generación automática de páginas "man". Esto es fácil de hacer, salvo el
problema de copiar la página man a los directorios de sistema. Supongo que
puedo indicar como requisito que MANPATH incluya /usr/local/share/man, o
comprobarlo de antemano.
Puntos no resueltos:
- Documentación de las funciones. El script padre sirve a su vez de API, y
actualmente cualquier script necesita inspeccionarlo para ver qué funciones
tiene implementadas. Puedo escribir una página man específica, pero aún así
no estaría mal poder definir una forma de poder hacer las funciones
autodescriptivas.
Por otro lado, he desarrollado esto porque no he visto nada equivalente.
No obstante, es probable que exista. ¿Alguien conoce alternativas? ¿Alguna
sugerencia?
Supongo que podría dar de alta un proyecto en sourceforge con esto, pero no
creo que tuviera mucho tráfico ni interés, y en pocos meses seguramente
parecería como "muerto". Supongo que lo subiré a mi web como mini-proyecto en
cuanto tenga solución para la auto-documentación.
Un saludo,
Jose.