Estoy tratando de crear algunos informes de errores usando una trampa para llamar a una función en todos los errores:
Trap "_func" ERR
¿Es posible obtener desde qué línea se envió la señal ERR? El caparazón es bash.
Si hago eso, puedo leer e informar qué comando se usó y registrar / realizar algunas acciones.
¿O tal vez me estoy yendo mal?
Probé con lo siguiente:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
Y $LINENO
está regresando 2. No funciona.
bash
shell-script
error-handling
trap
Mechaflash
fuente
fuente
bashdb
. Parece que el primer argumentotrap
puede contener variables que se evalúan en el contexto deseado. Entoncestrap 'echo $LINENO' ERR'
debería funcionar.trap 'echo $LINENO' ERR
. El primer argumentotrap
es laecho $LINENO
cita completa . Esto es en bash.trap 'echo $LINENO' ERR
, con comillas simples, no comillas dobles. Con el comando que escribió,$LINENO
se expande cuando se analiza la línea 2, por lo que la trampa esecho 2
(o mejor dichoECHO 2
, la que saldríabash: ECHO: command not found
).Respuestas:
Como se señaló en los comentarios, su cita es incorrecta. Necesita comillas simples para evitar que
$LINENO
se expanda cuando la línea de captura se analiza por primera vez.Esto funciona:
Ejecutándolo:
fuente
echo hello | grep foo
No parece arrojar un error para mí. ¿Estoy malinterpretando algo?grep
tiene un estado de salida de 0 si hubo una coincidencia, 1 si no hubo coincidencia y> 1 por un error. Puede verificar el comportamiento en su sistema conecho hello | grep foo; echo $?
También puede usar el 'llamador' integrado de bash:
también imprime el nombre del archivo:
fuente
Realmente me gusta la respuesta dada por @Mat arriba. Sobre la base de esto, escribí un pequeño ayudante que da un poco más de contexto para el error:
Podemos inspeccionar el script para la línea que causó la falla:
Aquí está en un pequeño script de prueba:
Cuando lo ejecutamos obtenemos:
fuente
$(caller)
los datos de '' para dar el contexto, incluso si la falla no está en el script actual sino en una de sus importaciones. ¡Muy bonito sin embargo!Inspirado por otra respuesta, aquí hay un controlador de errores contextuales más simple:
También puede usar awk en lugar de cola y cabeza si es necesario.
fuente
Aquí hay otra versión, inspirada en @sanmai y @unpythonic. Muestra líneas de script alrededor del error, con números de línea y el estado de salida, usando tail & head, ya que parece más simple que la solución awk.
Mostrando esto como dos líneas aquí para facilitar la lectura: puede unir estas líneas en una si lo prefiere (preservando
;
):Esto funciona bastante bien con
set -euo pipefail
( modo estricto no oficial ): cualquier error variable indefinido da un número de línea sin disparar laERR
pseudo-señal, pero los otros casos muestran contexto.Salida de ejemplo:
fuente
Sí,
LINENO
y lasBASH_LINENO
variables son útiles para obtener la línea de falla y las líneas que conducen a ella.No, solo falta la
-q
opción con grep ...... Con la
-q
opcióngrep
volverá0
portrue
y1
parafalse
. Y en Bash estrap
noTrap
...Aquí hay un trampero que puede ser útil para depurar cosas que tienen un poco más de complejidad ciclomática ...
failure.sh
... y un script de uso de ejemplo para exponer las diferencias sutiles en cómo configurar la trampa anterior para el rastreo de funciones también ...
example_usage.sh
Lo anterior se probó en Bash versión 4+, así que deje un comentario si necesita algo para versiones anteriores a la cuatro, o abra un problema si no logra atrapar fallas en sistemas con una versión mínima de cuatro.
Las principales conclusiones son ...
-E
provoca errores en funciones a burbujear-o functrace
causas permite más verbosidad cuando algo dentro de una función fallaLas comillas simples se usan alrededor de la llamada de función y las comillas dobles se usan alrededor de argumentos individuales.
Las referencias
LINENO
yBASH_LINENO
se pasan en lugar de los valores actuales, aunque esto podría acortarse en versiones posteriores de vinculados a trap, de modo que la línea de falla final llegue a la salidaSe pasan los valores
BASH_COMMAND
y el estado de salida ($?
), primero para obtener el comando que devolvió un error, y segundo para garantizar que la trampa no se active en estados sin errorY aunque otros pueden estar en desacuerdo, creo que es más fácil construir una matriz de salida y usar printf para imprimir cada elemento de la matriz en su propia línea ...
... también el
>&2
bit al final hace que los errores vayan a donde deberían (error estándar), y permite capturar solo errores ...Como se muestra en estos y otros ejemplos en Stack Overflow, hay muchas formas de crear una ayuda de depuración utilizando utilidades integradas.
fuente