Ho un file bash di cui ho bisogno per reindirizzare tutto l'output su un file, registro di debug e sul terminale. Devo reindirizzare sia stdout che stderr al debug e registrarlo per tutti i comandi nello script.
Non voglio aggiungere 2>&1 | tee -a $DEBUG
per ogni singolo comando nel file. Potrei vivere con | tee -a $DEBUG
.
Ricordo che c'era un modo per farlo con qualcosa come exec 2>&1
.
Attualmente sto usando qualcosa come il seguente:
#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG
ma non funziona. Qualcuno ha una soluzione/può spiegare la causa?
Risposta accettata:
Per quanto riguarda una soluzione per reindirizzare molti comandi contemporaneamente:
#!/bin/bash
{
somecommand
somecommand2
somecommand3
} 2>&1 | tee -a $DEBUGLOG
Perché la tua soluzione originale non funziona:exec 2>&1 reindirizzerà l'output dell'errore standard allo standard output della tua shell, che, se esegui lo script dalla console, sarà la tua console. il reindirizzamento della pipe sui comandi reindirizzerà solo l'output standard del comando.
Dal punto di vista di somecommand
, il suo output standard va in una pipe collegata a tee
e l'errore standard va nello stesso file/pseudofile dell'errore standard della shell, che reindirizzerai allo standard output della shell, che sarà la console se esegui il tuo programma dalla console.
L'unico vero modo per spiegarlo è vedere cosa succede davvero:
L'ambiente originale della tua shell potrebbe assomigliare a questo se lo esegui dal terminale:
stdin -> /dev/pts/42
stdout -> /dev/pts/42
stderr -> /dev/pts/42
Dopo aver reindirizzato l'errore standard nell'output standard (exec 2>&1
), tu... praticamente non cambi nulla. Ma se reindirizzi l'output standard dello script su un file, ti ritroverai con un ambiente come questo:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /dev/pts/42
Quindi reindirizzare l'errore standard della shell nello standard output finirebbe in questo modo:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /your/file
L'esecuzione di un comando erediterà questo ambiente. Se esegui un comando e lo reindirizza al tee, l'ambiente del comando sarebbe:
stdin -> /dev/pts/42
stdout -> pipe:[4242]
stderr -> /your/file
Quindi l'errore standard del tuo comando va ancora in ciò che la shell usa come errore standard.
Correlati:${!FOO} e zsh?
Puoi effettivamente vedere l'ambiente di un comando guardando in /proc/[pid]/fd
:usa ls -l
per elencare anche il contenuto del collegamento simbolico. Il il file qui è l'input standard,
1
è l'output standard e 2
è un errore standard. Se il comando apre più file (e la maggior parte dei programmi lo fa), li vedrai anche tu. Un programma può anche scegliere di reindirizzare o chiudere il proprio input/output standard e riutilizzare ,
1
e 2
.