¿Hay alguna forma de depurar un script bash? Por ejemplo, algo que imprime una especie de registro de ejecución como "línea de llamada 1", "línea de llamada 2", etc.
Estos le dan un rastro de lo que se está ejecutando. (Ver también 'Aclaración' cerca del final de la respuesta).
A veces, necesita controlar la depuración dentro del script. En ese caso, como me recordó Cheeto , puedes usar:
set-x
Esto activa la depuración. Luego puede apagarlo nuevamente con:
set+x
(Puede averiguar el estado de seguimiento actual analizando $-, los indicadores actuales, para x).
Además, los shells generalmente proporcionan opciones ' -n' para 'no ejecución' y ' -v' para modo 'detallado'; puede usarlos en combinación para ver si el shell cree que podría ejecutar su script, ocasionalmente útil si tiene una cita desequilibrada en alguna parte.
Existe la opinión de que la -xopción ' ' en Bash es diferente de otras shells (ver los comentarios). El Manual de Bash dice:
-X
Imprima una traza de comandos simples, forcomandos, casecomandos, selectcomandos y forcomandos aritméticos y sus argumentos o listas de palabras asociadas después de que se expanden y antes de que se ejecuten. El valor de la PS4variable se expande y el valor resultante se imprime antes del comando y sus argumentos expandidos.
Eso no parece indicar un comportamiento diferente en absoluto. No veo ninguna otra referencia relevante a ' -x' en el manual. No describe diferencias en la secuencia de inicio.
Aclaración : en sistemas como un cuadro típico de Linux, donde ' /bin/sh' es un enlace simbólico a ' /bin/bash' (o donde se encuentre el ejecutable Bash), las dos líneas de comando logran el efecto equivalente de ejecutar el script con el seguimiento de ejecución activado. En otros sistemas (por ejemplo, Solaris, y algunas variantes más modernas de Linux), /bin/shno es Bash, y las dos líneas de comando darían resultados (ligeramente) diferentes. En particular, ' /bin/sh' estaría confundido por construcciones en Bash que no reconoce en absoluto. (En Solaris, /bin/shes un shell Bourne; en Linux moderno, a veces es Dash, un shell más pequeño, más estrictamente solo POSIX). Cuando se invoca por un nombre como este, la línea 'shebang' (' #!/bin/bash' vs '#!/bin/sh'
El manual de Bash tiene una sección sobre el modo Bash POSIX que, al contrario de una versión antigua pero errónea de esta respuesta (ver también los comentarios a continuación), describe en gran detalle la diferencia entre 'Bash invocado como sh' y 'Bash invocado como bash'.
Al depurar un script de shell (Bash), será sensato y sensato, incluso necesario, utilizar el shell nombrado en la línea shebang con la -xopción. De lo contrario, puede (¿tendrá?) Obtener un comportamiento diferente al depurar al ejecutar el script.
Él especificó un bashguión. ¡Y ejecutar un script bash con sh -xhará que se comporte completamente diferente! Por favor actualice su respuesta.
lhunath
1
@lhunath: ¿De qué manera 'sh -x' (o 'bash -x') hace que un script se comporte de manera completamente diferente? Obviamente, envía información de rastreo a stderr; eso es un hecho (aunque no se menciona en mi respuesta). Pero que mas? Uso 'bash' como 'sh' en Linux y MacOS X y no he notado un problema grave.
Jonathan Leffler
66
Hay diferencias, en el inicio y en tiempo de ejecución. Están completamente documentados en la distribución Bash.
TheBonsai
44
Aquí hay un enlace al documento bash: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Si Bash se invoca con el nombre sh, intenta imitar el comportamiento de inicio de las versiones históricas de sh como lo más cerca posible, a la vez que se ajusta al estándar posix también '
thethinman
66
Y use el indicador de PS4 para dar más información útil como:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani
28
He usado los siguientes métodos para depurar mi script.
set -ehace que el script se detenga inmediatamente si algún programa externo devuelve un estado de salida distinto de cero. Esto es útil si su secuencia de comandos intenta manejar todos los casos de error y en caso de que no lo logre quedar atrapado.
set -x fue mencionado anteriormente y es sin duda el más útil de todos los métodos de depuración.
set -n También podría ser útil si desea verificar su secuencia de comandos en busca de errores de sintaxis.
straceTambién es útil para ver qué está pasando. Especialmente útil si no ha escrito el guión usted mismo.
Aplicar un script a un script (es decir, crear un shell ejecutando el script) es un método de depuración de shell extraño (pero puede funcionar para un conjunto limitado de problemas).
TheBonsai
1
Admito que es extraño y también muy detallado, pero si limita la salida de strace a unas pocas llamadas al sistema, se vuelve útil.
1
Tenga en cuenta que strace -fes necesario si también desea encontrar errores en los procesos iniciados por el script. (lo que lo hace mucho más detallado, pero sigue siendo útil si lo limita a las llamadas al sistema que le interesan).
Pero, encuentro que los métodos de depuración de script "estándar" son ineficientes, poco intuitivos y difíciles de usar. Para aquellos acostumbrados a depuradores de GUI sofisticados que ponen todo a su alcance y hacen que el trabajo sea fácil para problemas fáciles (y posibles para problemas difíciles), estas soluciones no son muy satisfactorias.
Lo que hago es usar una combinación de DDD y bashdb. El primero ejecuta el segundo, y el segundo ejecuta su script. Esto proporciona una interfaz de usuario de múltiples ventanas con la capacidad de recorrer el código en contexto y ver variables, apilar, etc., sin el esfuerzo mental constante de mantener el contexto en su cabeza o seguir enumerando la fuente.
Acabo de descubrir ddd gracias a tu respuesta. En Ubuntu 12.04.3 (64 bits), la versión de apt-sources no funciona. Tuve que compilar e instalar desde la fuente para comenzar a depurar mi script bash. Las instrucciones aquí - askubuntu.com/questions/156906/… ayudaron.
Chronodekar
Si, eso es un problema. Lo resolví hace tiempo con algunas secuencias de comandos: 'dddbash' instala / construye DDD, elimina la versión anterior si es incorrecta, instala bashdb, etc. (La respuesta se ha editado con esta información ahora)
Stabledog
10
También puede escribir "set -x" dentro del script.
$ cat test.sh
ARRAY=("hello there" world)for x in $ARRAY;do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:for x in $ARRAY;do^-- SC2128:Expanding an array without an index only gives the first element.
corrige el error, primero intenta ...
$ cat test.sh
ARRAY=("hello there" world)for x in ${ARRAY[@]};do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:for x in ${ARRAY[@]};do^-- SC2068:Double quote array expansions, otherwise they're like $* and break on spaces.
Para descascarado: descargue el zip e impórtelo en eclipse a través de ayuda -> instale un nuevo software: archivo local Para basheclipse: copie los frascos en el directorio dropins de eclipse
Esta es una respuesta límite de solo enlace (ver también aquí ). Debería ampliar su respuesta para incluir tanta información como sea posible, al menos el mínimo necesario para lograr lo que está sugiriendo, y usar los enlaces solo como referencia. Básicamente, las publicaciones en Stack Overflow (y todo Stack Exchange) deben ser independientes. Eso significa que debe haber suficiente información en su respuesta para que el lector no tenga que ir fuera del sitio para recibir instrucciones. En este momento, ese no es el caso para esta respuesta.
Makyen
Esta es la primera respuesta que he encontrado después de ver muchas que realmente muestran que es posible una depuración verdadera. Las respuestas estándar "set + x" coinciden perfectamente con una respuesta autónoma, pero ignoran casi deliberadamente las preguntas verdaderas sobre la depuración verdadera. Aplaudo esta respuesta 👏
Actualmente, BDB es compatible con los idiomas inglés y español. Para cambiar el idioma, edite el archivo / etc / default / bdb
abadjm el
la captura de pantalla parece interesante pero no pude hacer que se ejecute "bdb.sh: línea 32: bdbSTR [1]: variable independiente"; Por cierto, ¿mostrará los valores actuales de todas las variables establecidas en cada paso que hacemos en el código?
Acuario Power
2
set + x = @ECHO OFF, set -x = @ECHO ON.
Puede agregar una -xvopción al Shebang estándar de la siguiente manera:
#!/bin/bash -xv
-x: Muestra los comandos y sus argumentos a medida que se ejecutan. -v: Muestra las líneas de entrada del shell a medida que se leen.
ltracees otra utilidad de Linux similar a strace. Sin embargo, ltraceenumera todas las llamadas a la biblioteca que se llaman en un proceso ejecutable o en ejecución. Su nombre en sí proviene del rastreo de llamadas de biblioteca. Por ejemplo:
Hay una buena cantidad de detalles sobre el registro de scripts de shell a través de varaibles globales de shell. Podemos emular el tipo similar de inicio de sesión en el script de shell: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
La publicación tiene detalles sobre niveles de registro de introducción como INFO, DEBUG, ERROR. Detalles de seguimiento como entrada de script, salida de script, entrada de función, salida de función.
Respuestas:
Estos le dan un rastro de lo que se está ejecutando. (Ver también 'Aclaración' cerca del final de la respuesta).
A veces, necesita controlar la depuración dentro del script. En ese caso, como me recordó Cheeto , puedes usar:
Esto activa la depuración. Luego puede apagarlo nuevamente con:
(Puede averiguar el estado de seguimiento actual analizando
$-
, los indicadores actuales, parax
).Además, los shells generalmente proporcionan opciones '
-n
' para 'no ejecución' y '-v
' para modo 'detallado'; puede usarlos en combinación para ver si el shell cree que podría ejecutar su script, ocasionalmente útil si tiene una cita desequilibrada en alguna parte.Existe la opinión de que la
-x
opción ' ' en Bash es diferente de otras shells (ver los comentarios). El Manual de Bash dice:-X
Imprima una traza de comandos simples,
for
comandos,case
comandos,select
comandos yfor
comandos aritméticos y sus argumentos o listas de palabras asociadas después de que se expanden y antes de que se ejecuten. El valor de laPS4
variable se expande y el valor resultante se imprime antes del comando y sus argumentos expandidos.Eso no parece indicar un comportamiento diferente en absoluto. No veo ninguna otra referencia relevante a '
-x
' en el manual. No describe diferencias en la secuencia de inicio.Aclaración : en sistemas como un cuadro típico de Linux, donde '
/bin/sh
' es un enlace simbólico a '/bin/bash
' (o donde se encuentre el ejecutable Bash), las dos líneas de comando logran el efecto equivalente de ejecutar el script con el seguimiento de ejecución activado. En otros sistemas (por ejemplo, Solaris, y algunas variantes más modernas de Linux),/bin/sh
no es Bash, y las dos líneas de comando darían resultados (ligeramente) diferentes. En particular, '/bin/sh
' estaría confundido por construcciones en Bash que no reconoce en absoluto. (En Solaris,/bin/sh
es un shell Bourne; en Linux moderno, a veces es Dash, un shell más pequeño, más estrictamente solo POSIX). Cuando se invoca por un nombre como este, la línea 'shebang' ('#!/bin/bash
' vs'#!/bin/sh
'El manual de Bash tiene una sección sobre el modo Bash POSIX que, al contrario de una versión antigua pero errónea de esta respuesta (ver también los comentarios a continuación), describe en gran detalle la diferencia entre 'Bash invocado como
sh
' y 'Bash invocado comobash
'.Al depurar un script de shell (Bash), será sensato y sensato, incluso necesario, utilizar el shell nombrado en la línea shebang con la
-x
opción. De lo contrario, puede (¿tendrá?) Obtener un comportamiento diferente al depurar al ejecutar el script.fuente
bash
guión. ¡Y ejecutar un script bash consh -x
hará que se comporte completamente diferente! Por favor actualice su respuesta.export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
He usado los siguientes métodos para depurar mi script.
set -e
hace que el script se detenga inmediatamente si algún programa externo devuelve un estado de salida distinto de cero. Esto es útil si su secuencia de comandos intenta manejar todos los casos de error y en caso de que no lo logre quedar atrapado.set -x
fue mencionado anteriormente y es sin duda el más útil de todos los métodos de depuración.set -n
También podría ser útil si desea verificar su secuencia de comandos en busca de errores de sintaxis.strace
También es útil para ver qué está pasando. Especialmente útil si no ha escrito el guión usted mismo.fuente
strace -f
es necesario si también desea encontrar errores en los procesos iniciados por el script. (lo que lo hace mucho más detallado, pero sigue siendo útil si lo limita a las llamadas al sistema que le interesan).set -e
es ... controversiales .Esta respuesta es válida y útil: https://stackoverflow.com/a/951352
Pero, encuentro que los métodos de depuración de script "estándar" son ineficientes, poco intuitivos y difíciles de usar. Para aquellos acostumbrados a depuradores de GUI sofisticados que ponen todo a su alcance y hacen que el trabajo sea fácil para problemas fáciles (y posibles para problemas difíciles), estas soluciones no son muy satisfactorias.
Lo que hago es usar una combinación de DDD y bashdb. El primero ejecuta el segundo, y el segundo ejecuta su script. Esto proporciona una interfaz de usuario de múltiples ventanas con la capacidad de recorrer el código en contexto y ver variables, apilar, etc., sin el esfuerzo mental constante de mantener el contexto en su cabeza o seguir enumerando la fuente.
Hay una guía para configurar eso aquí: http://ubuntuforums.org/showthread.php?t=660223
fuente
También puede escribir "set -x" dentro del script.
fuente
Encontré la utilidad Shellcheck y puede que algunas personas lo encuentren interesante https://github.com/koalaman/shellcheck
Un pequeño ejemplo:
corrige el error, primero intenta ...
Intentemoslo de nuevo...
¡encuentra ahora!
Es solo un pequeño ejemplo.
fuente
Instale VSCode , luego agregue la extensión de depuración bash y estará listo para depurar en modo visual. ver aquí en acción.
fuente
Use eclipse con los complementos sin cáscara y basheclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Para descascarado: descargue el zip e impórtelo en eclipse a través de ayuda -> instale un nuevo software: archivo local Para basheclipse: copie los frascos en el directorio dropins de eclipse
Siga los pasos que proporciona https://sourceforge.net/projects/basheclipse/files/?source=navbar
Escribí un tutorial con muchas capturas de pantalla en http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
fuente
Construí un depurador Bash. Solo inténtalo. Espero que ayude https://sourceforge.net/projects/bashdebugingbash
fuente
Puede agregar una
-xv
opción al Shebang estándar de la siguiente manera:-x
: Muestra los comandos y sus argumentos a medida que se ejecutan.-v
: Muestra las líneas de entrada del shell a medida que se leen.ltrace
es otra utilidad de Linux similar astrace
. Sin embargo,ltrace
enumera todas las llamadas a la biblioteca que se llaman en un proceso ejecutable o en ejecución. Su nombre en sí proviene del rastreo de llamadas de biblioteca. Por ejemplo:Fuente
fuente
Creo que puedes probar este depurador de Bash: http://bashdb.sourceforge.net/ .
fuente
Algún truco para depurar intento guiones:
Utilizando
set -[nvx]
Además de
y
para detener el volcado.
Me gustaría hablar sobre qué
set -v
volcado es tan pequeño como un resultado menos desarrollado.Volcado de variables o rastreo sobre la marcha
Para probar algunas variables, uso alguna vez esto:
para añadir:
en la línea 18 y en funcionamiento resultante de la escritura (con args ), sin tener que modificarlas.
por supuesto, esto podría usarse para agregar
set [+-][nvx]
:se agregará
declare -p v1 v2 >&2
después de la línea 18,set -x
antes de la línea 22 yset +x
antes de la línea 26.pequeña muestra:
Nota: ¡La preocupación
$LINENO
se verá afectada por las modificaciones sobre la marcha !(Para ver el script resultante sin ejecutar, simplemente suelte
bash <(
y) arg1 arg2
)Paso a paso, tiempo de ejecución
Echa un vistazo a mi respuesta sobre cómo perfilar scripts de bash
fuente
Hay una buena cantidad de detalles sobre el registro de scripts de shell a través de varaibles globales de shell. Podemos emular el tipo similar de inicio de sesión en el script de shell: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
La publicación tiene detalles sobre niveles de registro de introducción como INFO, DEBUG, ERROR. Detalles de seguimiento como entrada de script, salida de script, entrada de función, salida de función.
Registro de muestra:
fuente