ich mache set -e
gewöhnlichBash-Skript beim ersten Fehler stoppen.
Alles funktioniert einwandfrei, sofern ich den Befehl nicht mit folgendem verwende &&
:
$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$
im Vergleich zu:
$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$
Im ersten Beispiel wird immer noch ein Echo ausgegeben I'm running!
, im zweiten jedoch nicht. Warum verhalten sie sich unterschiedlich?
UPD. Ähnliche Frage:https://stackoverflow.com/questions/6930295/set-e-and-short-tests
Antwort1
Dies ist dokumentiertes Verhalten.man-Seite für bash(1)sagt, fürset -e
,
Die Shell wird nicht beendet, wenn der fehlgeschlagene Befehl Teil der Befehlsliste ist, die unmittelbar auf ein
while
oderuntil
Schlüsselwort folgt, oder Teil des Tests, der auf die reservierten Wörterif
oder folgt.elif
Teil eines Befehls, der in einer&&
oder||
Liste ausgeführt wird mit Ausnahme des Befehls nach dem letzten&&
oder||
, jeder Befehl in einer Pipeline außer dem letzten oder wenn der Rückgabewert des Befehls mit invertiert wird!
.
[Hervorhebung hinzugefügt.]
Und dasPOSIXShell-BefehlsspracheSpezifikation bestätigt, dass dies das richtige Verhalten ist:
Die
-e
Einstellung soll ignoriert werden, wenn die zusammengesetzte Liste nach dem reservierten Wortwhile
,until
,if
, oder ausgeführt wird, eine Pipeline, die mit dem reservierten Wort beginnt, oder ein beliebiger Befehl einer UND-ODER-Liste außer dem letzten.elif
!
UndAbschnitt 2.9.3Listendieses Dokuments definiert
Eine UND-ODER-Liste ist eine Folge von einer oder mehreren Pipelines, die durch die Operatoren "
&&
" und "||
" getrennt sind.
Antwort2
In manchen Situationen ist die set -e
Option wirkungslos. Dabei handelt es sich um das Standardverhalten, das auf alle POSIX-kompatiblen Shells portierbar ist.
Der fehlgeschlagene Befehl ist Teil der Pipeline:
false | true; echo printed
wird gedruckt printed
.
Dabei wird nur der Ausfall der Pipeline selbst berücksichtigt:
true | false; echo 'not printed'
wird nichts drucken.
Der fehlgeschlagene Befehl wird in der zusammengesetzten Liste nach dem reservierten Wort while
, until
, if
, ausgeführt, in einer Pipeline, die mit dem reservierten Wort beginnt, oder in einem beliebigen Befehl als Teil einer Liste außer dem letzten:elif
!
&&
||
false || true; echo printed
Der letzte Befehl schlägt immer noch fehl und hat set -e
folgende Auswirkungen:
true && false; echo 'not printed'
DerUnterschaleschlägt in einem zusammengesetzten Befehl fehl:
(false; echo 'not printed') | cat -; echo printed
Antwort3
meine Vermutung ist, dass die Wenn-Dann-Bedingung insgesamt als „Wahr“ ausgewertet wird.
Ich habe es versucht
set -e
if cd not_existing_dir
then echo 123
fi
echo "I'm running! =P"
Wer gibt
-bash: cd: not_existing_dir: No such file or directory
I'm running! =P
Der Fehlercode wird durch die If-Bedingung abgefangen, sodass Bash das Ende der Ausführung nicht auslöst.