bash: establece -x registros en el archivo

18

Tengo un script de shell con set -xuna salida detallada / de depuración:

#!/bin/bash

set -x
command1
command2
...

El resultado se ve así:

+ command1
whatever output from command1
+ command2
whatever output from command2

Mi problema es que la salida de la shell (causada por set -x) va al stderr, mezclada con la salida de los comandos ( command1, command2, ...). Me encantaría tener la salida "normal" en la pantalla (como si el script se ejecutara sin set -x) y la salida "extra" de bash por separado en un archivo.

Entonces me gustaría tener esto en la pantalla:

whatever output from command1
whatever output from command2

y esto en un archivo de registro:

+ command1
+ command2

(también está bien si el archivo de registro tiene todo junto)

El set -x 2> fileobviamente doens't toman el efecto deseado, porque no es la salida del comando set, pero cambiar el comportamiento de la fiesta.

El uso bash 2> filede todo el script tampoco hace lo correcto, porque redirige el stderr de cada comando que se ejecuta también en este shell, por lo que no veo el mensaje de error de los comandos.

redseven
fuente
2
Mi google-fu parece estar fuerte esta mañana: envíe la salida bash -x al archivo de registro sin interrumpir la salida estándar
steeldriver

Respuestas:

20

En base a esta respuesta de ServerFault, envíe la salida bash -x al archivo de registro sin interrumpir la salida estándar , las versiones modernas de bash incluyen BASH_XTRACEFDespecíficamente para especificar un descriptor de archivo alternativo para la salida deset -x

Entonces, por ejemplo, puedes hacer

#!/bin/bash

exec 19>logfile
BASH_XTRACEFD=19

set -x
command1
command2
...

para enviar la salida del set -xarchivo al logfiletiempo que conserva la salida estándar regular y las secuencias de error estándar para los siguientes comandos.

Tenga en cuenta que el uso de fd 19 es arbitrario: solo necesita ser un descriptor disponible (es decir, no 0, 1, 2 u otro número que ya haya asignado).

conductor de acero
fuente
De hecho, guarda el registro de seguimiento de bash por separado, sin embargo, hace que sea muy difícil leer las 2 salidas (stdout + stderr en la pantalla y el seguimiento de bash en los archivos de registro) ya que están completamente fuera de sincronización. Vea la solución que acabo de publicar .
redseven
4

Después de más de un año, he encontrado la solución correcta para tener tanto el resultado "normal" (stdout + stderr - bash trace) en la pantalla como todos juntos (stdout + stderr + bash trace) en un archivo (bash.log) :

exec   > >(tee -ia bash.log)
exec  2> >(tee -ia bash.log >& 2)
exec 19> bash.log

export BASH_XTRACEFD="19"
set -x

command1
command2
redseven
fuente
Esa es solo la combinación de la respuesta de Steeldriver y esta .
jarno
3

Steeldriver te dio un enfoque. Alternativamente, puede simplemente redirigir STDERR a un archivo:

script.sh 2> logfile

Sin embargo, eso significa que tanto el resultado creado por la set -xopción como cualquier otro mensaje de error producido irán al archivo. La solución de Steeldriver solo redirigirá la set -xsalida, que probablemente sea lo que desea.

terdon
fuente
"... tanto el resultado creado por la opción set -x como cualquier otro mensaje de error producido irán al archivo". Y es por eso que no funciona para mí. Mi problema principal es que no veo fácilmente "errores reales", porque toda esta salida de bash va al stderr. Redirigir los mensajes de error de los comandos también me ocultaría los "errores reales" de una manera diferente.
redseven
@redseven Me temo que lo que estás pidiendo no está muy claro entonces. ¿Podrías editar tu pregunta y aclarar? Intente evitar el uso del término "salida" para cualquier cosa que no vaya a ser estándar. ¿Desea separar i) salida normal; ii) cualquier error arrojado por su comando y iii) set -x? ¿No es suficiente la respuesta de Steeldriver entonces? Si no, muéstrenos un script simple que podamos copiar y díganos cómo le gustaría que se comportara.
terdon
@steeldriver ya ha respondido perfectamente la pregunta.
redseven
@redseven ah, genial entonces. Dado que su comentario llegó mucho más tarde, pensé que aún necesitaba algo y no pude ver cómo la respuesta de steeldriver no pudo resolver su problema. Me alegro de que todo esté resuelto entonces.
terdon