2010-09-03 5 views
17

Ich muss die Ausgabe und Fehler eines Befehls in meinem Bash-Skript erfassen und wissen, ob der Befehl erfolgreich war oder nicht.bash variable capture stderr und stdout getrennt oder erhalten exit-wert

Im Moment bin ich erfassen beide wie folgt aus:

output=$(mycommand 2>&1) 

Ich muss dann den Exit-Wert von mycommand überprüfen. Wenn es fehlschlägt, muss ich etwas mit der Ausgabe machen, wenn der Befehl erfolgreich war, muss ich die Ausgabe nicht berühren.

Da ich die Ausgabe erfassen, überprüfen $? ist immer eine 0, da es bash gelungen ist, die Ausgabe in die Variable einzufangen. Dieses

ist ein sehr zeitkritische Skript, so dass wir versuchen, alle langsamen Lösungen zu vermeiden, wie in eine Datei ausgeben und wieder lesen auf.

Wenn ich stdout zu einer Variablen und stderr zu einem anderen erfassen könnte, das würde mein Problem lösen, weil ich einfach überprüfen könnte, ob die Fehlervariable leer war oder nicht.

Danke.

+4

See [BashFAQ/002] (http://mywiki.wooledge.org/BashFAQ/002) und [BashFAQ/047] (http://mywiki.wooledge.org/BashFAQ/047). –

Antwort

8

Welche Version von bash verwenden Sie? Die Erfassung des Ausgangs hat Null Auswirkungen auf dem Return-Code mit meiner Version, 4.1.5:

pax> false; echo $? 
1 
pax> echo $? 
0 
pax> x=$(false 2>&1) ; echo $? 
1 

Es ist nicht immer eine gute Idee, auf Standardfehler ist nicht leer zu verlassen, Fehler zu erkennen. Viele Programme geben keine Fehler aus, sondern verlassen sich ausschließlich auf den Rückkehrcode .

+0

Ich habe vergessen zu erwähnen, dass ich die Ausgabe meines Befehls zu einem anderen pipe. Obwohl ich das in einem separaten Kommando erledigen kann. Vielen Dank. – mhost

+3

Vorsicht! Wenn 'local x = $ (false 2> &1) ; echo $?' Oder 'set x = $ (false 2> &1) ; echo $?' (Anmerkung ** 'local/set' ** am Anfang) ist, wird '0' nicht ausgegeben '1' als letzter Befehlslauf ist' local/set'. –

10

Das Problem scheint nur zu manifestieren, wenn die Ausgabe in eine lokalen Variable innerhalb einer Funktion erfasst wird:

$ echo $BASH_VERSION 
3.2.48(1)-release 
$ false; echo $? 
1 
$ echo $? 
0 
$ x=$(false 2>&1) ; echo $? 
1 
$ function f { 
> local x=$(false 2>&1) ; echo $? 
> } 
$ f 
0 
$ function g { 
> x=$(false 2>&1) ; echo $? 
> } 
$ g 
1 

Beachten Sie, dass nur die Funktion f, die x zu einem lokalen einfängt, kann das Verhalten ausdrücken. Insbesondere funktioniert die Funktion g, die dasselbe tut, aber ohne das Schlüsselwort "local".

Man kann daher keine lokale Variable verwenden und sie nach der Verwendung möglicherweise 'aufheben'.

EDIT NVRAM weist darauf hin, dass die lokale Erklärung vorher das Problem zu vermeiden gemacht werden kann:

$ function h { 
> local x 
> x=$(false 2>&1) ; echo $? 
> } 
$ h 
1 
+0

Sehr interessant! Das passiert sowohl in bash als auch in der (posix) Shell. – Gregor

+3

Tatsächlich ist $? Für die lokale Variablendeklaration gesetzt, wenn Sie es einfach durch deklarieren selbst dann, _there_ es in einer separaten Zeile zuzuweisen, wird es funktionieren, wie Sie wollen. Mit anderen Worten, fügen Sie ** local x ** über Ihre Zeile mit ** x = ** – NVRAM

Verwandte Themen