Tengo un archivo bash que necesito para redirigir todos los resultados a un archivo, registro de depuración y al terminal. Necesito redirigir tanto stdout como stderr a la depuración y registrarlos para todos los comandos en el script.
No quiero agregar 2>&1 | tee -a $DEBUG
para cada comando en el archivo. Podría vivir con | tee -a $DEBUG
.
Recuerdo que había una forma de hacerlo con algo como exec 2>&1
.
Actualmente estoy usando algo como lo siguiente:
#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG
Pero no funciona. ¿Alguien tiene una solución/puede explicar la causa?
Respuesta aceptada:
En cuanto a una solución para redirigir muchos comandos a la vez:
#!/bin/bash
{
somecommand
somecommand2
somecommand3
} 2>&1 | tee -a $DEBUGLOG
Por qué su solución original no funciona:exec 2>&1 redirigirá la salida de error estándar a la salida estándar de su shell, que, si ejecuta su script desde la consola, será su consola. la redirección de tubería en los comandos solo redirigirá la salida estándar del comando.
Desde el punto de vista de somecommand
, su salida estándar va a una tubería conectada a tee
y el error estándar va al mismo archivo/pseudoarchivo que el error estándar del shell, que redirige a la salida estándar del shell, que será la consola si ejecuta su programa desde la consola.
La única forma verdadera de explicarlo es ver qué sucede realmente:
El entorno original de su shell podría tener este aspecto si lo ejecuta desde la terminal:
stdin -> /dev/pts/42
stdout -> /dev/pts/42
stderr -> /dev/pts/42
Después de redirigir el error estándar a la salida estándar (exec 2>&1
), tú... básicamente no cambias nada. Pero si redirige la salida estándar del script a un archivo, terminará con un entorno como este:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /dev/pts/42
Luego, redirigir el error estándar de shell a la salida estándar terminaría así:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /your/file
Ejecutar un comando heredará este entorno. Si ejecuta un comando y lo canaliza hasta el tee, el entorno del comando sería:
stdin -> /dev/pts/42
stdout -> pipe:[4242]
stderr -> /your/file
Por lo tanto, el error estándar de su comando aún entra en lo que el shell usa como su error estándar.
Relacionado:${!FOO} y zsh?
De hecho, puede ver el entorno de un comando mirando en /proc/[pid]/fd
:usa ls -l
para enumerar también el contenido del enlace simbólico. El el archivo aquí es una entrada estándar,
1
es salida estándar y 2
es el error estándar. Si el comando abre más archivos (y la mayoría de los programas lo hacen), también los verá. Un programa también puede optar por redirigir o cerrar su entrada/salida estándar y reutilizar ,
1
y 2
.