¿Cómo depurar un script bash?

Estoy teniendo algunos problemas con algunos scripts en bash, sobre errores y comportamientos inesperados. Me gustaría investigar las causas de los problemas para poder aplicar arreglos. ¿Hay alguna manera de que pueda activar algún tipo de «modo de depuración» para bash, para obtener más información?

Respuesta

Inicie su script bash con bash -x ./script.sh o agregue en su script set -x para ver la salida de depuración.


Adicional con bash 4.1 o posterior:

Si desea escribir la salida de depuración en un archivo separado, agregue esto a su script:

exec 5> debug_output.txt BASH_XTRACEFD="5" 

Consulte: https://stackoverflow.com/a/25593226/3776858


Si desea ver los números de línea, agregue esto:

PS4="$LINENO: " 


Si tiene acceso a logger comando, entonces puede usar esto para escribir la salida de depuración a través de su syslog con la marca de tiempo, el nombre del script y el número de línea:

#!/bin/bash exec 5> >(logger -t $0) BASH_XTRACEFD="5" PS4="$LINENO: " set -x # Place your code here 

Puede usar la opción -p del comando logger para configurar una instalación y un nivel individuales para escribir la salida a través de syslog local en su propio archivo de registro.

Comentarios

  • -v también puede ayudar (imprime cada línea a medida que se ejecutan. se puede combinar con -x). Y vea también: bashdb.sourceforge.net
  • Otro recurso maravilloso es: shellcheck .net
  • ¿Qué significa » exec 5 > » hacer?
  • @aggsol: si usa BASH_XTRACEFD="5" bash escribe la salida de seguimiento generada cuando set -x es habilitado para descriptor de archivo 5. exec 5> >(logger -t $0) redirige la salida del descriptor de archivo 5 a logger comando.
  • Me pregunto si puede obtener el número de línea y la ruta del script de shell o el nombre en PS4.

Respuesta

Usando set -x

Siempre uso set -x y set +x. Puede envolver las áreas en las que desea ver qué sucede con ellas para aumentar o disminuir la verbosidad.

#!/bin/bash set -x ..code to debug... set +x 

log4bash

También si ha realizado un trabajo de desarrollo y está familiarizado con el estilo de los registradores que se conocen con los nombres log4j, log4perl, etc., puede que desee utilizar log4bash .

extracto

Seamos realistas: el eco simple y corriente simplemente no sirve. log4bash es un intento de tener un mejor registro para los scripts de Bash (es decir, hacer que el registro en Bash apesta menos).

Desde allí puede hacer cosas como esta en su Secuencias de comandos bash:

#!/usr/bin/env bash source log4bash.sh log "This is regular log message... log and log_info do the same thing"; log_warning "Luke ... you turned off your targeting computer"; log_info "I have you now!"; log_success "You"re all clear kid, now let"s blow this thing and go home."; log_error "One thing"s for sure, we"re all gonna be a lot thinner."; # If you have figlet installed -- you"ll see some big letters on the screen! log_captains "What was in the captain"s toilet?"; # If you have the "say" command (e.g. on a Mac) log_speak "Resistance is futile"; 

que dan como resultado este tipo de salida:

        ss1

log4sh

Si necesita algo más portátil, también está el log4sh anterior. Funciona de manera similar a log4bash, disponible aquí:

Comentarios

  • En Ubuntu, tengo alias say="spd-say" en mi .bashrc, que imita el say comando de otras distribuciones o OS X.
  • set -vx sería una buena combinación si se usa con trap – trap read debug. Esto le permite pasar línea por línea y ver los resultados

Respuesta

Hay «un depurador de bash, bashdb , que es un paquete instalable en muchas distribuciones. Utiliza el modo de depuración extendido integrado de bash (shopt -s extdebug). Se parece mucho a gdb; aquí hay una sesión de muestra para darle un poco de sabor:

$ ls 1st.JPG 2ndJPG.JPG $ cat ../foo.sh for f in *.JPG do newf=${f/JPG/jpg} mv $f $newf done $ bashdb ../foo.sh (foo.sh:1): 1: for f in *.JPG bashdb<0> next (foo.sh:3): 3: newf=${f/JPG/jpg} bashdb<1> next (foo.sh:4): 4: mv $f $newf 

Como en gdb, la instrucción se muestra justo antes de que esté a punto de ejecutarse. Así que podemos examinar las variables para ver qué hará la declaración antes de hacerlo.

bashdb<2> print $f $newf 1st.JPG 1st.jpg bashdb<3> next (foo.sh:1): 1: for f in *.JPG bashdb<4> next (foo.sh:3): 3: newf=${f/JPG/jpg} bashdb<5> next (foo.sh:4): 4: mv $f $newf bashdb<6> print $f $newf 2ndJPG.JPG 2ndjpg.JPG 

¡Eso no es lo que queremos! Veamos el expansión de parámetros de nuevo.

bashdb<7> print $f ${f/JPG/jpg} 2ndJPG.JPG 2ndjpg.JPG bashdb<8> print $f ${f/JPG$/jpg} 2ndJPG.JPG 2ndJPG.JPG bashdb<9> print $f ${f/%JPG/jpg} 2ndJPG.JPG 2ndJPG.jpg 

Bien, eso funciona. Establezcamos newf en el valor correcto.

bashdb<10> eval newf=${f/%JPG/jpg} $? is 0 bashdb<11> print $f $newf 2ndJPG.JPG 2ndJPG.jpg 

Se ve bien. Continúe con el script.

bashdb<12> next Debugged program terminated normally. Use q to quit or R to restart. $ ls 1st.jpg 2ndJPG.jpg 

Respuesta

El método estándar para depurar scripts en la mayoría de shells basados en Bourne, como bash es escribir set -x en la parte superior de la secuencia de comandos. Esto hará que bash sea más detallado sobre lo que se está haciendo / ejecutando y cómo se evalúan los argumentos.

-x Print commands and their arguments as they are executed. 

esto es útil tanto para el intérprete como para los scripts internos. Por ejemplo:

$ find "$fileloc" -type f -prune "$filename" -print + find /var/adm/logs/morelogs -type f -prune "-name *.user" -print find: unknown predicate "-name *.user" $ find "$fileloc" -type f -prune $filename -print + find /var/adm/logs/morelogs -type f -prune -name "*.user" -print find: "/var/adm/logs/morelogs": No such file or directory 

En lo anterior podemos ver por qué la búsqueda falla debido a algunas comillas simples.

Para desactivar la función, simplemente escriba set +x.

Responder

Uso de Eclipse

Puede utilizar el entorno combinado de Eclipse y Shelt con el script «_DEBUG.sh» vinculado a continuación.

Cambio de shells

Por Por defecto, la herramienta de desarrollo Shelt utiliza /bin/dash como intérprete. Cambié esto a /bin/bash para tener una mejor compatibilidad con la mayoría de los ejemplos de shell en la web y mi entorno.

NOTA: Puede cambiar esto yendo a: Ventana -> Preferencia -> Script de Shell -> Intérpretes

Instrucciones de configuración

El paquete Debugger tiene los pasos para usar el script _DEBUG.sh para la depuración de su script, que es básicamente (el archivo readme.txt):

  1. Crear proyecto de script de shell: Archivo -> Nuevo -> Otro – > Secuencia de comandos de shell

-> Asistente de proyecto de script de shell .

  • Cree un archivo de secuencia de comandos Bash: Archivo -> Nuevo -> Archivo . Para este ejemplo, será script.sh. La extensión debe ser «.sh» y es imprescindible.
  • Copie el archivo _DEBUG.sh en la carpeta del proyecto.
  • Inserte el el siguiente texto en la parte superior del archivo script.sh:

    . _DEBUG.sh 
  • Si el archivo se crea en Microsoft Windows, entonces asegúrese de ejecutar el Archivo -> Convertir delimitadores de línea a -> Unix .

  • Establezca una configuración de inicio de depuración: Ejecute -> Configuraciones de depuración -> Secuencia de comandos Bash … Hay 2 campos para configurar aquí:

    a) «Script Bash:» – Ruta en el espacio de trabajo de Eclipse al script Bash para depurar.
    e) «Puerto del depurador:» 33333

  • Cambie a la perspectiva de depuración. Inicie la sesión de depuración. Ejecute script.sh desde el shell bash.

  • La interfaz de usuario de depuración de bash

    ingrese la descripción de la imagen aquí

    Este depurador de bash tiene todas las características de los depuradores de programación estándar, tales como:

    • Interruptor de punto de interrupción
    • Operación paso a paso único
    • Funciones y subrutinas Step-in, Step-out, Step-over
    • Examinar código o variables en cualquier momento mientras se ejecuta el script

    El entorno de desarrollo integrado (Integrated Development Environment) Shelt (Shell Script Editor) tiene una ventaja adicional de realizar la verificación de contexto, resaltar y sangrar mientras escribe su script. Si no se sangra correctamente, es posible que de inmediato pueda marcar / local muchos errores allí.

    Luego hay otros beneficios del IDE como:

    • Lista de tareas TODO
    • Tarea Mylyn
    • Lista de marcadores
    • Múltiples Edición de ventanas
    • Uso compartido remoto del entorno

    Comentarios

    • Sugerencia interesante. Es bueno saber que Bash puede depurarse así.

    Respuesta

    Un recurso maravilloso apareció en los últimos años: http://shellcheck.net

    le muestra más que el bash normal, lo que le permite a uno encontrar fácilmente esas molestas comillas sin cerrar o rizadas corchetes, etc.

    Solo asegúrese de no pegar información confidencial (ips, contraseñas, etc.) en la red … (especialmente porque es http, sin cifrar) (creo que shellcheck también está disponible para descargar, pero no estoy seguro)

    Responder

    Hoy en día, existe la depuración de VS Code Bash.

    https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug

    Tiene «Paso dentro / fuera / over «y también muestra el valor de cada variable.

    Captura de pantalla de VS Code Bash Debug

    Comentarios

    • esta respuesta no aborda la pregunta en el contexto correcto; asumiendo la línea de comando ya que no se mencionó IDE

    Respuesta

    simplemente use:

    #!/bin/bash -x 

    lo mismo para el shell:

    #!/bin/sh -x 

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *