2010-03-09 13 views
35

erhalten (und anhängen) stdout und stderr in eine Datei zu umleiten, während es auch auf dem Endgerät angezeigt wird, ich dies tun:bash: Umleitung (und hängen) stdout und stderr Datei und Terminal und die richtige Exit-Status

command 2>&1 | tee -a file.txt 

Gibt es jedoch eine andere Möglichkeit, dies zu tun, so dass ich einen genauen Wert für den Exit-Status bekomme?

Das heißt, wenn ich $? testen, möchte ich den Exit-Status von command, nicht den Exit-Status von tee sehen.

Ich weiß, dass ich ${PIPESTATUS[0]} hier statt $? verwenden kann, aber ich bin auf der Suche nach einer anderen Lösung, die nicht erfordern würde, zu überprüfen.

+2

Warum möchten Sie nicht 'PIPESTATUS' verwenden? –

+0

Duplikate: http://stackoverflow.com/questions/985876/tee-and-exit-status, http: // stackoverflow.com/questions/1221833/bash-tee-output- und-capture-exit-status – jpalecek

Antwort

30

Vielleicht haben Sie den Ausgang Wert von PIPESTATUS in $?

command 2>&1 | tee -a file.txt ; (exit ${PIPESTATUS}) 
6

Eine weitere Möglichkeit stellen könnten, mit einigen bash Aromen, ist auf der pipefail Option zu aktivieren:

pipefail

Wenn gesetzt, der Rückgabewert einer Pipeline ist der Wert der letzten (ganz rechts) comm und zum Beenden mit einem Status ungleich oder Null, wenn alle Befehle in der Pipeline erfolgreich beendet wurden. Diese Option ist standardmäßig deaktiviert.

set -o pipefail 
... 
command 2>&1 | tee -a file.txt || echo "Command (or tee?) failed with status $?" 

Dies vorausgeschickt, ist der einzige Weg zur Erreichung PIPESTATUS Funktionalität portably (zB so ist es auch mit POSIX sh arbeiten würde) ist ein bisschen gewunden, dh es erfordert eine temporäre Datei ein fortzupflanzen Rohr Exit-Status zurück zum Mutter Shell-Prozess:

{ command 2>&1 ; echo $? >"/tmp/~pipestatus.$$" ; } | tee -a file.txt 
if [ "`cat \"/tmp/~pipestatus.$$\"`" -ne 0 ] ; then 
    ... 
fi 

oder, zur Wiederverwendung Einkapseln:

log2file() { 
    LOGFILE="$1" ; shift 
    { "[email protected]" 2>&1 ; echo $? >"/tmp/~pipestatus.$$" ; } | tee -a "$LOGFILE" 
    MYPIPESTATUS="`cat \"/tmp/~pipestatus.$$\"`" 
    rm -f "/tmp/~pipestatus.$$" 
    return $MYPIPESTATUS 
} 

log2file file.txt command param1 "param 2" || echo "Command failed with status $?" 

oder, allgemeiner vielleicht:

save_pipe_status() { 
    STATUS_ID="$1" ; shift 
    "[email protected]" 
    echo $? >"/tmp/~pipestatus.$$.$STATUS_ID" 
} 

get_pipe_status() { 
    STATUS_ID="$1" ; shift 
    return `cat "/tmp/~pipestatus.$$.$STATUS_ID"` 
} 

save_pipe_status my_command_id ./command param1 "param 2" | tee -a file.txt 
get_pipe_status my_command_id || echo "Command failed with status $?" 

... 

rm -f "/tmp/~pipestatus.$$."* # do this in a trap handler, too, to be really clean 
3

Es gibt eine obskure POSIX Art und Weise, dies zu tun:

exec 4>&1; R=$({ { command1; echo $? >&3 ; } | { command2 >&4; } } 3>&1); exec 4>&- 

Es wird die Variable R auf den Rückgabewert von command1 gesetzt und Rohr Ausgang command1 zu command2, dessen Ausgabe auf den Ausgang der übergeordneten Shell umgeleitet wird.

4

Verwendung Prozess Substitution:

command > >(tee -a "$logfile") 2>&1 

T-Shirt läuft in einer Subshell so $? hält den Exit-Status Befehl.

Verwandte Themen