Cómo depurar scripts en Bash

Hola lector, esta entrada, tratara de amplificar una que hice, hace ya un tiempo atrás, que producto de mi parón forzado quedo en el tintero, pero que puede ser útil, tanto como recordatorio como aprendizaje para cualquiera que este interesado en entrar al scripting. Como ya debes saber la depuración o debugging, es el proceso para encontrar y corregir los errores, en el código fuente de cualquier software, tanto un simple script, como un programa, propiamente dicho. Si quiere darle un vistazo a ese post anterior, te lo dejo a continuación Manejo de errores en scripting, seria bueno que empieces por allí, si acabas de iniciarte.

Cuando recién comenzaba a hacer alguna automatización desde linea de comandos o algún desarrollo, recuerdo que pasaba muchas horas tratando de encontrar el error en mi código y, al final, podría ser algo muy simple, como una coma. Es posible que también te hayas enfrentado a la misma situación.

Saber cómo usar la técnica de depuración adecuada te ayudara a resolver los errores rápidamente. A diferencia de otros lenguajes como Python, Java, etc., no existe una herramienta de depuración para bash donde pueda establecer puntos de interrupción, pasar por alto el código, etc. Pero puedes habilitar algunas opciones en tus scripts para hacer un debugging, que pueda ayudarte, de la siguiente manera:

Habilita opciones de depuración (debugging flags) desde el shell al llamar al script:

Habilita opciones de depuración pasando los indicadores de depuración a la línea shebang en el script.

Habilita opciones de depuración usando el comando set del script.

El comando set es un comando integrado de shell que se puede usar para controlar los parámetros de bash y alterar su comportamiento de ciertas maneras. Será ampliamente utilizado dentro de los scripts de shell, ya sea para la depuración o para habilitar el modo bash estricto. Normalmente, no ejecutarás comandos de configuración desde la terminal para modificar el comportamiento de su shell. Usa set – -help, para obtener mayor información.

Debugging

Antes de conocer las opciones de depuración, te debo comentar que puedes depurar, tanto el script completo o solo una parte determinada del código. Debe usar el comando set para habilitar y deshabilitar las opciones de depuración.

Echa un vistazo al siguiente código. set -x habilitará el modo xtrace para el script y set +x deshabilitará el modo xtrace. Todo lo que se encuentre entre set -x y set +x se ejecutará en modo de depuración xtrace.

Cuando se trabaja con variables en bash, la desventaja es que si tratamos de usar una variable no definida, el script no fallará con algún mensaje de error como «Variable no definida». En su lugar, imprimirá una cadena vacía.

En el código a continuación, obtengo información del usuario y la almaceno en la variable $OBJECT. Intenté ejecutar el operador de prueba (-f y -d) en la variable $OBJECT1 que no está definida.

Cuando ejecuto este código, debería haberme arrojado un error, pero no lo hizo e incluso el script salió con el código de retorno cero. Para anular este comportamiento, usa el flag -u, bash -u scriptname. generando un mensaje de error cuando se use una variable indefinida, mostrando un mensaje de error Unbound variable.

También puede configurar -u usando el comando set o pasarlo como argumento al shebang.

Xtrace – To the Rescue!

Este es el modo que uso cuando depuro scripts bash para errores lógicos. El modo Xtrace mostrará el código línea por línea pero con los parámetros expandidos. Ahora puedo ejecutar el mismo script anterior, en modo xtrace y ver exactamente dónde está ocurriendo el problema.

Para depurar este problema, puedo ejecutar el script en modo xtrace pasando el indicador -x. bash -x scriptname. Esto me dice que hay cadenas vacías asignadas a las declaraciones condicionales -f y -d.

El signo + que ve en stdout se puede cambiar poniendo la variable PS4 en el script. De forma predeterminada, PS4 está configurado en (+), lanzando un: echo $PS4, podrás verificarlo. Para cambiarlo. lanza algo como esto:

cambiando el signo +, por >>, en el stdout de tu script.

También puedes configurar el modo Xtrace usando el comando set o pasarlo como argumento al shebang.

No olvides, que puedes redirigir los registros de depuración a un archivo en lugar de imprimirlos en la terminal. Por ejemplo al código anterior agregue unas lineas, luego del shebang. asignano un descriptor de archivo 6 al archivo .log y BASH_XTRACEFD=»6″ redirigirá los registros de depuración de xtrace al descriptor de archivo 6.

Cuando ejecuto este código en lugar de imprimir la salida de xtrace en la terminal, se redirigirá al archivo salida_debug.log. Usando cat, podremos leerlo dentro de la terminal.

Modo estricto de Bash

Para eliminar todos los posibles errores que hemos visto, puedes agregar algunas opciones en cada script.

  • -e Salga del script si algún comando arroja un código de salida distinto de cero.
  • -u Hacer que el script falle si se usa un nombre de variable indefinido.
  • pipefail Si algún comando en la tubería falla, el código de salida se considerará para toda
  • IFS Separador de campo interno, establecerlo en nueva línea (\ n) y (\ t) hará que la división ocurra solo en nueva línea y tabulacion.

O

Usemos TRAP

Imagina un escenario en el que se activa el script, pero deseas cancelar lo con un CTRL+C. En ese caso, se enviará SIGINT a tu script. Con TRAP, puedes capturar esta señal y ejecutar algunos comandos o funciones.

El codigo, a continuación tiene una función llamada limpieza que se ejecutará cuando se pase SIGINT al script.

Imprima el código usando el modo Verbose

En el modo detallado (verbose), el código se imprimirá antes de devolver el resultado. Si el programa requiere una entrada interactiva, en ese caso solo se imprimirá esa línea seguida de un bloque de códigos.

Seguido a este párrafo, hay un programa simple que obtiene un objeto del usuario y verifica si object es un archivo o directorio que usa una declaración condicional.

Ejecutado el código anterior, primero imprimirá el código y luego esperará la entrada del usuario, hecho esto el resto del código se imprimirá seguido de la salida. $OBJECT es directorio o archivo, segun sea el caso. Como en los anteriores casos, puedes configurar el modo verbose usando set o en el shebang. set -v, set -o verbose o #! /bin/bash -v

Errores en sintaxis – modo noexec

Los errores de sintaxis son muy comunes en los programas. Es posible que haya perdido una cita o no haya podido salir del ciclo, etc. Puedes usar el flag -n (modo noexec) para validar la sintaxis antes de ejecutar el programa.

Si, se te olvido de poner una llave, una corchete, unas comillas o una coma, gracias a esta flag, podrás saberlo. mostrando mensajes de error de sintaxis. De forma predeterminada, cuando ejecutas un script, bash validará la sintaxis y arrojará estos errores incluso sin usar el modo noexec. De misma manera, como antes, puedes usar set -n, set -o noexec o #! /bin/bash -n

Conclusión

Pues buen lector, espero te sirva todos estos alcances, sobre la depuracion de scripts en bash. La gran diferencia con otros lenguajes de programación, es que no tiene herramientas de depuración aparte de algunas opciones integradas. A veces, estas opciones serán más que suficientes para realizar el trabajo y te pueden salvar de algún apuro. Hasta otro post lector, buenas vibras.

Happy Hacking!

Deja un comentario