¿Alguien sabe de algún recurso que hable sobre las mejores prácticas o patrones de diseño para scripts de shell (sh, bash, etc.)?
design-patterns
bash
shell
usuario14437
fuente
fuente
Respuestas:
Escribí scripts de shell bastante complejos y mi primera sugerencia es "no". La razón es que es bastante fácil cometer un pequeño error que obstaculiza tu script, o incluso hacerlo peligroso.
Dicho esto, no tengo otros recursos para pasarte sino mi experiencia personal. Esto es lo que normalmente hago, que es exagerado, pero tiende a ser sólido, aunque muy detallado.
Invocación
Haz que tu script acepte opciones largas y cortas. tenga cuidado porque hay dos comandos para analizar opciones, getopt y getopts. Use getopt mientras enfrenta menos problemas.
Otro punto importante es que un programa siempre debe devolver cero si se completa con éxito, no cero si algo salió mal.
Llamadas a funciones
Puede llamar a funciones en bash, solo recuerde definirlas antes de la llamada. Las funciones son como scripts, solo pueden devolver valores numéricos. Esto significa que debe inventar una estrategia diferente para devolver valores de cadena. Mi estrategia es usar una variable llamada RESULTADO para almacenar el resultado y devolver 0 si la función se completó limpiamente. Además, puede generar excepciones si devuelve un valor diferente de cero y luego establecer dos "variables de excepción" (mine: EXCEPTION y EXCEPTION_MSG), la primera contiene el tipo de excepción y la segunda un mensaje legible por humanos.
Cuando llama a una función, los parámetros de la función se asignan a los vars especiales $ 0, $ 1, etc. Le sugiero que los ponga en nombres más significativos. declare las variables dentro de la función como locales:
Situaciones propensas a errores
En bash, a menos que declare lo contrario, una variable no establecida se usa como una cadena vacía. Esto es muy peligroso en caso de error tipográfico, ya que la variable mal escrita no se informará y se evaluará como vacía. utilizar
para evitar que esto suceda. Sin embargo, tenga cuidado, porque si hace esto, el programa abortará cada vez que evalúe una variable indefinida. Por esta razón, la única forma de verificar si una variable no está definida es la siguiente:
Puede declarar variables como de solo lectura:
Modularización
Puede lograr una modularización "similar a Python" si usa el siguiente código:
luego puede importar archivos con la extensión .shinc con la siguiente sintaxis
importar "AModule / ModuleFile"
Que se buscará en SHELL_LIBRARY_PATH. Como siempre importa en el espacio de nombres global, recuerde prefijar todas sus funciones y variables con un prefijo apropiado, de lo contrario corre el riesgo de conflictos de nombres. Yo uso doble guión bajo como el punto de python.
Además, ponga esto como lo primero en su módulo
Programación orientada a objetos
En bash, no puedes hacer programación orientada a objetos, a menos que construyas un sistema bastante complejo de asignación de objetos (pensé en eso. Es factible, pero loco). En la práctica, sin embargo, puede hacer "programación orientada a Singleton": tiene una instancia de cada objeto, y solo una.
Lo que hago es: defino un objeto en un módulo (ver la entrada de modularización). Luego defino vars vacíos (análogos a las variables miembro) una función init (constructor) y funciones miembro, como en este código de ejemplo
Señales de captura y manejo
Encontré esto útil para atrapar y manejar excepciones.
Consejos
Si algo no funciona por alguna razón, intente reordenar el código. El orden es importante y no siempre es intuitivo.
ni siquiera consideres trabajar con tcsh. no admite funciones, y es horrible en general.
Espero que ayude, aunque tenga en cuenta. Si tiene que usar el tipo de cosas que escribí aquí, significa que su problema es demasiado complejo para resolverlo con Shell. usa otro idioma Tuve que usarlo debido a factores humanos y legado.
fuente
getopt
vsgetopts
?getopts
es más portátil y funciona en cualquier shell POSIX. Especialmente dado que la pregunta es las mejores prácticas de shell en lugar de las mejores prácticas de bash específicamente, apoyaría el cumplimiento de POSIX para admitir múltiples shells cuando sea posible.Eche un vistazo a la Guía avanzada de secuencias de comandos Bash para obtener mucha sabiduría sobre las secuencias de comandos de shell, no solo Bash, tampoco.
No escuches a las personas que te dicen que mires a otros idiomas, posiblemente más complejos. Si las secuencias de comandos de shell satisfacen tus necesidades, úsalas. Desea funcionalidad, no fantasía. Los nuevos idiomas brindan nuevas y valiosas habilidades para su currículum, pero eso no ayuda si tiene trabajo que debe hacerse y ya conoce shell.
Como se indicó, no hay muchas "mejores prácticas" o "patrones de diseño" para el script de shell. Los diferentes usos tienen diferentes directrices y sesgos, como cualquier otro lenguaje de programación.
fuente
El script de shell es un lenguaje diseñado para manipular archivos y procesos. Si bien es excelente para eso, no es un lenguaje de propósito general, así que siempre trate de pegar la lógica de las utilidades existentes en lugar de recrear una nueva lógica en el script de shell.
Aparte de ese principio general, he recopilado algunos errores comunes de script de shell .
fuente
Hubo una gran sesión en OSCON este año (2008) sobre este tema: http://assets.en.oreilly.com/1/event/12/Shell%20Scripting%20Craftsmanship%20Presentation%201.pdf
fuente
Sepa cuándo usarlo. Para comandos de pegado rápido y sucio, está bien. Si necesita tomar más que pocas decisiones no triviales, bucles, cualquier cosa, vaya a Python, Perl y modularice .
El mayor problema con el caparazón es a menudo que el resultado final se ve como una gran bola de barro, 4000 líneas de golpe y crecimiento ... y no puedes deshacerte de él porque ahora todo tu proyecto depende de ello. Por supuesto, comenzó en 40 líneas de hermosa fiesta.
fuente
Fácil: use python en lugar de scripts de shell. Obtiene un aumento de casi 100 veces en la legibilidad, sin tener que complicar nada que no necesita, y preservando la capacidad de desarrollar partes de su script en funciones, objetos, objetos persistentes (zodb), objetos distribuidos (pyro) casi sin ningún tipo de código extra
fuente
use set -e para no avanzar después de los errores. Intente hacerlo compatible con sh sin depender de bash si desea que se ejecute en no Linux.
fuente
Para encontrar algunas "mejores prácticas", observe cómo las distribuciones de Linux (por ejemplo, Debian) escriben sus scripts de inicio (generalmente se encuentran en /etc/init.d)
La mayoría de ellos no tienen "bash-isms" y tienen una buena separación de los ajustes de configuración, los archivos de la biblioteca y el formato de origen.
Mi estilo personal es escribir un script maestro que defina algunas variables predeterminadas y luego intente cargar ("fuente") un archivo de configuración que puede contener nuevos valores.
Intento evitar las funciones, ya que tienden a hacer que el script sea más complicado. (Perl fue creado para ese propósito).
Para asegurarse de que el script sea portátil, pruebe no solo con #! / Bin / sh, sino que también use #! / Bin / ash, #! / Bin / dash, etc. Pronto detectará el código específico de Bash.
fuente
O la cita anterior similar a lo que dijo Joao:
"Usa perl. Querrás saber bash pero no usarlo".
Lamentablemente olvidé quién dijo eso.
Y sí, en estos días recomendaría Python sobre Perl.
fuente