Bash-Skript mit „set -e“ stoppt nicht beim Befehl „… && …“

Bash-Skript mit „set -e“ stoppt nicht beim Befehl „… && …“

ich mache set -egewö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 whileoder untilSchlüsselwort folgt, oder Teil des Tests, der auf die reservierten Wörter ifoder folgt.elifTeil 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 -eEinstellung soll ignoriert werden, wenn die zusammengesetzte Liste nach dem reservierten Wort while, 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 -eOption 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 -efolgende 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.

verwandte Informationen