[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Sobre Bash



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.