Detectar errores y comprobar la sintaxis de los scripts de Bash

Escrito por el .
gnu-linux planeta-codigo
Enlace permanente Comentarios

El lenguaje de scripting Bash permite crear sencillos y no tan sencillos scripts para automatizar tareas del sistema o funciones. Dado que un script de Bash se interpreta no se compila un error no se detecta hasta llegar a la línea con el error que puede ser en la mitad del script dejando la tarea sin finalizar correctamente. Para evitar errores antes de la ejecución del script Bash ofrece varias opciones.

Linux

A pesar de los lenguajes interpretados como Python o Groovy, los scripts de Bash siguen siendo muy útiles e incluso más adecuados como herramienta en algunas tareas. Python y Groovy son lenguajes de programación de propósito general capaces de realizar tareas muy complejas al mismo tiempo que su código sigue siendo mantenible y legible. Ambos lenguajes son interpretados por lo que no requieren realizar un paso previo de compilación que hacen fácil tener un script sencillo en poco tiempo pero que suponen un problema al realizar modificaciones por introducir errores de compilación que no se manifiestan hasta llegar a la línea de código errónea.

Bash es un intérprete de comandos que permite ejecutar scripts, Bash está orientado al propósito de ejecutar comandos del sistema, obtener sus códigos de retorno, la salida de los comandos, y permitir ciertas expresiones que aunque no llegan a la capacidad de los lenguajes de propósito general permite realizar bucles, condicionales, crear funciones con argumentos y tener variables.

Un script de Bash grande es un problema ya que al ser interpretado también ocurre que hasta no se ejecuta la línea del script se manifieste el error. Si la tarea se queda a medias y no termina correctamente sobretodo cuando hay acciones que realizan modificaciones dejan el sistema en un estado inconsistente que no permiten reejecutar el script una vez corregido su error.

Bash ofrece varias opciones para capturar algunos de los errores en la ejecución de los scripts. Algunas de estas opciones las he utilizado en el script de instalación de Arch Linux que está basado en Bash. El script tiene un tamaño de unas 3K+ líneas de código es fácil introducir un error, ya que no tengo tiempo para probar y menos justo el caso en el que se produce el error por la cantidad de opciones posibles que permite de configuración.

Opciones para detectar errores

Bash permite establecer varias opciones de ejecución. La opción -e permite detener el script en cuanto un comando se ejecuta y devuelve un código de error distinto de cero que como convención indica que el comando se ejecutó con algún error, un valor distinto de cero significa un código de error o código de estado que tiene un significado que indica el motivo. Otra opción, con -u permite detener el script cuando una variable de entorno intenta evaluar su valor y la variable aún no está definida, continuar sin el valor adecuado supone probablemente que el script realiza acciones incorrectas.

Por defecto al ejecutar un script este solo genera como resultado la salida de los comandos que ejecuta, para depurar los scripts o ver que comandó están ejecutando la opción -x trace emite el comando ejecutado que permite ver el valor de los argumentos del comando y ver qué valores han tomado los argumentos de las variables de ese comando.

Opciones de Bash para comprobar un script

Otra forma de probar un script es ejecutar las líneas del script pero sin ejecutar los comandos de esas líneas. La opción -n permite ejecutar un script sin ejecutar los comandos. Esto tiene la parte buena de que los comandos no se ejecutan con las posibles acciones de modificación. Para algunos scripts esto es una forma de probarlos con ciertas garantías de que funciona, para los complejos no es suficiente.

Dado que la opción -n no ejecuta los comandos tampoco se obtienen los valores correctos de modo que la línea de ejecución seguramente no sea la misma en el caso de haber sentencias condicionales, bucles o llamadas a funciones. En realidad, lo ideal para probar un script es establecer la opción -n solo para aquellos comandos que realizan acciones de modificación, los comandos que realizan acciones para obtener datos al no realizar modificaciones y ser inocuos se pueden ejecutar sin nin problema. De este modo, desactivando la ejecución únicamente de los comandos de modificación es posible probar una mayor parte del script.

La opción se puede activar en la ejecución del script dentro del script cambiando el valor de la opción para desactivar la ejecución de los comandos con set -n o volver a activar la ejecución de los comandos set +n. En este ejemplo el comando que emite el se ejecuta y su salida en la consola pero el comando ls no se ejecuta, ni siquiera sale en las trazas que genera -x xtrace.

1
2
3
4
5
6
7
8
#!/bin/bash
set -eu
set -x xtrace

pwd
set -n
ls
set +n
test.sh
1
2
3
+ pwd
/home/picodotdev/Descargas/Backup
+ set -n
test.out

Programa para validar la sintaxis de un script de Bash

Las opciones anteriores permiten validar los scripts de Bash en buena parte pero tienen limitaciones y dependiendo del código del script quizá no generen ningún error un script que en realidad tiene errores. Para una validación más completa la utilidad shellcheck realiza una validación que es capaz de detectar una mayor cantidad de errores, de forma más precisa y más sencilla. shellcheck realiza comprobaciones adicionales que se basan en entender la sintaxis de Bash y comprobar que el script tiene una sintaxis válida acorde a la definición del lenguaje.

Incluso en la web de shellcheck es posible realizar la validación sin necesidad de instalar el comando en el sistema local. Aún con el mejor esfuerzo que hace shellcheck por detectar errores algunos errores se deben a argumentos, opciones de comandos que son erróneas o argumentos con valores inválidos, shellcheck comprueba que la sintaxis del script sea válido pero sigue habiendo casos que en tiempo de ejecución se manifiestan como errores que en tiempo de validación no es posible detectar.

Para usarlo como comando en el sistema local se usa el siguiente comando para lo que es necesario instalar el correspondiente paquete de la distribución usada, en Arch Linux el paquete es shellcheck.

1
2
$ shellcheck alis.sh

shellcheck.sh


Comparte el artículo: