Envíe la salida bash -x al archivo de registro sin interrumpir la salida estándar

12

¿Hay alguna manera de enviar la información que se muestra ejecutando un script bash con la opción -x a un archivo, sin cambiar la salida estándar vista por un usuario que ejecuta el script?

Esta es una característica de depuración que me gustaría implementar en un script bash que usamos y que cambia con frecuencia.

Muy apreciado.

lo siento doctor de rosa
fuente

Respuestas:

21

La salida de -x va a stderr, no stdout. Pero incluso eso puede ser un problema: muchos scripts tendrán dependencias funcionales del contenido de stderr, y es un poco complicado tener las secuencias de depuración y stderr mezcladas en algunos casos.

Las versiones Bash> 4.1 ofrecen una solución diferente: la variable de entorno BASH_XTRACEFD le permite especificar un descriptor de archivo que se utilizará para enviar la secuencia de depuración. Esto puede ser un archivo o una tubería o cualquier otra bondad de Unix que desee.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Con un poco más de violín, puede hacer otras cosas, como hacer un 'tee' en las secuencias stdout y / o stdin, e intercalar aquellas con la salida de depuración, para que su registro esté más completo. Para obtener más detalles sobre esto, consulte /programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

La gran ventaja de este enfoque sobre las alternativas es que no está arriesgando cambios en el comportamiento de su script al inyectar la salida de depuración en stdout o stderr.

Stabledog
fuente
Vea también aquí cómo encontrar un descriptor de archivo no utilizado para el archivo.
Jarno
¿Es necesario cerrar el descriptor de archivo (es decir, línea exec 19>&-)? En mi experiencia, se cierra automáticamente cuando finaliza el script.
jarno
1
El código que se muestra arriba no asume que está ejecutando un script, o cuánto tiempo podría ser el script, etc. Es cierto que si solo hace lo que está haciendo este fragmento y lo coloca en un script, el identificador de archivo se cerrará solo porque todo el shell desaparece al final del script. Entonces, en ese caso de uso, no es estrictamente necesario cerrar el asa. Pero, en general, al codificar contra un recurso, es una buena práctica cerrar lo que ha abierto, porque entonces su código se puede usar en un contexto más amplio donde es más probable que la limpieza sea importante.
Stabledog
¿Por qué exportas BASH_XTRACEFD? ¿Por qué no solo establecer el valor para ello?
jarno
De todos modos, una forma alternativa de cerrar el descriptor de archivo es establecer un nuevo valor (por ejemplo, nulo) para BASH_XTRACEFD o desarmarlo.
jarno
4

set -xno envía nada a la salida estándar, por lo que no hay problema allí. Lo que hace es escribir en el error estándar, que va a la consola por defecto.

Lo que desea hacer es redirigir stdout a otro archivo, como este:

/bin/sh -x /my/script/file 2>/my/log/file
womble
fuente
1

Ver man tee.

Lo ejecuta como tee commandname filenamey mostrará los resultados de los comandos stdouty también los escribirá filename.

Sven
fuente