Mám bash soubor, který potřebuji přesměrovat veškerý výstup do jednoho souboru, protokolu ladění a také do terminálu. Potřebuji přesměrovat stdout i stderr na ladění a zaprotokolovat je pro všechny příkazy ve skriptu.
Nechci přidávat 2>&1 | tee -a $DEBUG
pro každý jednotlivý příkaz v souboru. Mohl bych žít s | tee -a $DEBUG
.
Pamatuji si, že existoval způsob, jak to udělat pomocí něčeho jako exec 2>&1
.
Momentálně používám něco jako následující:
#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG
ale to nejde. Má někdo řešení/může vysvětlit příčinu?
Přijatá odpověď:
Pokud jde o řešení přesměrování velkého množství příkazů najednou:
#!/bin/bash
{
somecommand
somecommand2
somecommand3
} 2>&1 | tee -a $DEBUGLOG
Proč vaše původní řešení nefunguje:exec 2>&1 přesměruje standardní chybový výstup na standardní výstup vašeho shellu, který, pokud spustíte skript z konzole, bude vaší konzolí. přesměrování roura u příkazů přesměruje pouze standardní výstup příkazu.
Z pohledu somecommand
, jeho standardní výstup jde do potrubí připojeného k tee
a standardní chyba jde do stejného souboru/pseudosouboru jako standardní chyba shellu, který přesměrujete na standardní výstup shellu, kterým bude konzole, pokud svůj program spustíte z konzole.
Jediný skutečný způsob, jak to vysvětlit, je vidět, co se skutečně děje:
Původní prostředí vašeho shellu může vypadat takto, pokud jej spustíte z terminálu:
stdin -> /dev/pts/42
stdout -> /dev/pts/42
stderr -> /dev/pts/42
Po přesměrování standardní chyby na standardní výstup (exec 2>&1
), v podstatě nic nezměníte. Ale pokud přesměrujete standardní výstup skriptu do souboru, skončíte s prostředím jako je toto:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /dev/pts/42
Pak by přesměrování standardní chyby shellu na standardní výstup skončilo takto:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /your/file
Spuštění příkazu toto prostředí zdědí. Pokud spustíte příkaz a přenesete jej do odpaliště, prostředí příkazu bude:
stdin -> /dev/pts/42
stdout -> pipe:[4242]
stderr -> /your/file
Standardní chyba vašeho příkazu tedy stále jde do toho, co shell používá jako svou standardní chybu.
Související:${!FOO} a zsh?
Prostředí příkazu můžete ve skutečnosti vidět v /proc/[pid]/fd
:použijte ls -l
také vypsat obsah symbolického odkazu. soubor zde je standardní vstup,
1
je standardní výstup a 2
je standardní chyba. Pokud příkaz otevře více souborů (a většina programů to udělá), uvidíte je také. Program se také může rozhodnout přesměrovat nebo zavřít svůj standardní vstup/výstup a znovu použít ,
1
a 2
.