2017-09-12 3 views
1

Ich habe ein einfaches Skript mit einer einfachen Funktion, die zu einem Fehler führen kann. Lassen Sie sich diese Funktion definieren, und es gebrochen:Keep set -e Einstellung innerhalb || oder &&

brokenFunction() { 
    ls "non-existing-folder" 
} 

Wenn wir diese Funktion in einem Block Erkennung auszuführen, wenn es gebrochen ist, es funktioniert gut:

brokenFunction || printf "It is broken\n" 

prints „Es ist gebrochen“

Jetzt

, lassen Sie sich die Funktion ein wenig komplexer machen, indem einen korrekten Befehl am Ende hinzufügen:

#!/bin/sh 

brokenFunction() { 
    ls "non-existing-folder" 
    printf "End of function\n" 
} 

brokenFunction || printf "It is broken\n" 

Dieses Skript druckt:

$ ./script.sh 
ls: cannot access 'non-existing-folder': No such file or directory 
End of function 

während ich die Funktion erwartet, bevor die Anweisung printf zu stoppen und den nächsten Block anzuzeigen „Es ist gebrochen“.

Und in der Tat, wenn ich den Ausgang Statuscode brokenFunction überprüfen, ist es 0.

versuchte ich set -e an die Spitze des Skripts hinzufügen. Das Verhalten ist immer noch das gleiche, aber der Exit-Code von brokenFunction, wenn er ohne || aufgerufen wird, wird jetzt 2. Wenn sie damit aufgerufen wird, ist der Statuscode immer noch 0.

Gibt es eine Möglichkeit, die set -e Einstellung in einer Funktion zu halten, die mit || aufgerufen wird?

EDIT: Ich habe gerade festgestellt, dass die Funktion in dem Beispiel nutzlos war. Ich stoße auf dasselbe Problem mit einem einfachen Block und einer Bedingung.

#!/bin/sh 
set -e 
{ 
    ls "non-existing-dir" 
    printf "End of block\n" 
} || { 
    printf "It is broken\n" 
} 

druckt

$ ./script.sh 
ls: cannot access 'non-existing-dir': No such file or directory 
End of block 
+1

fand ich, warum es nicht wie erwartet funktioniert: https://unix.stackexchange.com/questions/65532/why-does-set-e-not-work-inside Jetzt suche ich nur nach einer sauberen Lösung. – Dunatotatos

Antwort

0

Wie in man bash geschrieben wird set -e in manchen Kontexten ignoriert. Ein Befehl vor || oder && ist ein solcher Zusammenhang.

trap sieht hier wie eine mögliche Lösung aus. Eine Arbeits Alternative zum letzten Skript trap verwenden würde so aussehen:

#!/bin/sh 
abort() { 
    printf "It is broken\n" 
} 
trap 'abort' ERR 
(
    set -e 
    false 
    printf "End of block\n" 
) 
trap - ERR 

Einige Dinge haben hier bemerkt werden:

  • trap 'abort' ERR die abort Funktion jeden angehobenen Fehler bindet;
  • Der defekte Block wird aus zwei Gründen in einer Untershell ausgeführt. Erstens soll die Einstellung set -e im Block bleiben und die Randeffekte begrenzen. Zweitens wird diese Subshell bei einem Fehler (set -e Effekt) und nicht das gesamte Skript beendet;
  • trap - ERR am Ende setzt die trap Bindung zurück, was bedeutet, dass der folgende Teil des Skripts wie zuvor ausgeführt wird.

die Grenzeffekte zu testen, haben wir die zuvor nicht erwerbstätigen Teil hinzufügen:

#!/bin/sh 
abort() { 
    printf "It is broken\n" 
} 

trap 'abort' ERR 
(
    set -e 
    false 
    printf "End of block\n" 
) 
trap - ERR 

{ 
    false 
    printf "End of second block\n" 
} || { 
    printf "It is broken too\n" 
} 

druckt:

It is broken 
End of second block 
+0

'Trap ERR' ist nicht POSIX. Ich sollte es wahrscheinlich mit den 'set -e'-Parametern in' trap EXIT' ändern. – Dunatotatos

Verwandte Themen