Cómo mostrar el número de línea al ejecutar el script bash

89

Tengo un script de prueba que tiene muchos comandos y generará muchos resultados, uso set -xo set -vy set -e, por lo que el script se detendría cuando se produjera un error. Sin embargo, todavía me resulta bastante difícil localizar en qué línea se detuvo la ejecución para localizar el problema. ¿Existe un método que pueda generar el número de línea del script antes de que se ejecute cada línea? ¿O mostrar el número de línea antes de la exhibición de comandos generada por set -x? O cualquier método que pueda resolver mi problema de ubicación de línea de script sería de gran ayuda. Gracias.

dspjm
fuente

Respuestas:

159

Mencionas que ya estás usando -x. La variable PS4indica que el valor es el indicador impreso antes de que se repita la línea de comando cuando la -xopción está configurada y su valor predeterminado es :seguido de un espacio.

Puede cambiar PS4para emitir el LINENO(El número de línea en el script o función de shell que se está ejecutando actualmente).

Por ejemplo, si su secuencia de comandos dice:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

Ejecutarlo así imprimiría números de línea:

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtips ofrece lo último PS4que generaría todo lo que posiblemente necesite para el rastreo:

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
devnull
fuente
4
Me pregunto por qué nadie menciona esto para "¿Cómo depurar scripts de shell?" . Esto es mucho mejor que soloecho
Suvarna Pattayil
@VusP De acuerdo, echoes mejor evitar declaraciones innecesarias .
devnull
2
No puedo evitar sentir que -x debería imprimir números de línea. O, tal vez, nx debería incluir números de línea. Para mí, es uno de esos momentos "WTF" ...
jww
1
Hombre, desearía haber sabido sobre esa mezcla de PS4 antes ... Me habría ahorrado tantos dolores de cabeza
niken
2
\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'para algunos colores
Ulysse BN
34

En Bash, $LINENOcontiene el número de línea donde se ejecuta actualmente el script.

Si necesita saber el número de línea donde se llamó a la función, intente $BASH_LINENO. Tenga en cuenta que esta variable es una matriz.

Por ejemplo:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

Consulte aquí los detalles de las variables Bash.

Deqing
fuente
0

Solución simple (pero poderosa): coloque echoalrededor del código que cree que causa el problema y mueva echolínea por línea hasta que los mensajes ya no aparezcan en la pantalla, porque el script se ha detenido debido a un error antes.

Solución aún más poderosa: instale bashdbel depurador de bash y depure el script línea por línea

hek2mgl
fuente
2
echoHacer cosas alrededor puede ayudar en muchos casos, pero se queda corto cuando intenta aplicarlo en funciones que tienen una salida significativa y analizable.
Eliran Malka
1
@EliranMalka Punto justo. Puede hacer eco a stderr en ese caso:echo "foo" >&2
hek2mgl
1
... uno debe hacer eco a stderr en todos los casos cuando el propósito es mensajes que son de naturaleza diagnóstica.
Charles Duffy
0

Solución alternativa para proyectiles sin LINENO

En una secuencia de comandos bastante sofisticada, no me gustaría ver todos los números de línea; más bien me gustaría tener el control de la salida.

Definir una función

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

Úselo con comillas como

echo_line_no "this is a simple comment with a line number"

La salida es

16   "this is a simple comment with a line number"

si el número de esta línea en el archivo fuente es 16.

Básicamente, esto responde a la pregunta Cómo mostrar el número de línea al ejecutar un script bash para usuarios de ash u otros shells sin LINENO.

¿Algo más que agregar?

Por supuesto. ¿Por qué necesitas esto? ¿Cómo trabajas con esto? ¿Qué puedes hacer con esto? ¿Es este sencillo enfoque realmente suficiente o útil? ¿Por qué quieres jugar con esto?

¿Quiere saber más? Leer reflexiones sobre la depuración

kklepper
fuente