Bash-Skript mit `set -e` hört bei`… &&… `nicht auf

13

Ich verwende set -ezu Bash - Skript auf den ersten Fehler zu stoppen .

Alle funktionieren OK, es sei denn, ich verwende den Befehl mit &&:

$ 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
$

Das erste Beispiel I'm running!hört sich immer noch an , das zweite nicht. Warum verhalten sie sich anders?

UPD. Ähnliche Frage: /programming/6930295/set-e-and-short-tests

907th
quelle
Was erwarten Sie im ersten Beispiel?
Flup
@Flup Ich erwarte , dass nach erfolgloser Skript Stopp - cdBefehl
907.
1
In BashFAQ Nr. 105 finden Sie eine allgemeine Beschreibung der Orte, an denen das set -eVerhalten überraschend ist.
Charles Duffy
related: stackoverflow.com/questions/25794905/…
Ciro Santilli am

Antworten:

9

Dies ist dokumentiertes Verhalten. Die bash (1) Manpage sagt, für set -e,

Die Shell wird nicht beendet, wenn der fehlgeschlagene Befehl Teil der Befehlsliste ist, die unmittelbar auf ein whileoder until-Schlüsselwort folgt , Teil des Tests, der auf die ifoder elifreservierten Wörter folgt , Teil eines Befehls, der in einer &&oder ||-Liste ausgeführt wird, mit Ausnahme des Befehls, der auf das letzte &&oder ein|| beliebiges folgt Befehl in einer Pipeline vor dem letzten oder wenn der Rückgabewert des Befehls mit invertiert wird !.
[Betonung hinzugefügt.]

Und die POSIX - Shell Command Language Specification bestätigt , dass dies das richtige Verhalten ist:

Die -eEinstellung wird ignoriert, wenn die Verbindung des folgende Liste ausgeführt wird while, until, if, oder elifreservierte Wort, eine Rohrleitung mit dem Beginn !reservierten Wort oder jeder Befehl einer AND-OR - Liste außer den letzten.

und Abschnitt 2.9.3 Listen dieses Dokuments definiert

Eine UND-ODER-Liste ist eine Folge von einer oder mehreren Pipelines, die durch die Operatoren " &&" und " ||" getrennt sind.

G-Man sagt, "Monica wiedereinsetzen"
quelle
9

Die set -eOption hat in einigen Situationen keine Auswirkung. Dies ist das Standardverhalten und kann auf eine POSIX-kompatible Shell übertragen werden.


Der fehlgeschlagene Befehl ist Teil der Pipeline:

false | true; echo printed

wird gedruckt printed.

Und nur der Ausfall der Pipeline selbst wird berücksichtigt:

true | false; echo 'not printed'

druckt nichts.


Der ausgefallene Befehl Lauf in der Verbindung der folgenden Liste while, until, if, elifreserviertes Wort, beginnend eine Rohrleitung mit dem !reservierten Wort oder jeder Befehl als Teil &&oder ||Liste mit Ausnahme des letzten:

false || true; echo printed

Der letzte Befehl schlägt immer noch fehl set -ebetroffen zu machen :

true && false; echo 'not printed'

Die Subshell schlägt in einem zusammengesetzten Befehl fehl:

(false; echo 'not printed') | cat -; echo printed
cuonglm
quelle
Vielen Dank! Es wäre klarer zu verwenden echo "printed"und echo "not_printed"in Ihren Beispielen (anstelle von echo 1).
907.
3
Beachten Sie, set -edass YMMV mit verschiedenen Shells und sogar verschiedenen Versionen derselben Shell beendet (false && true); echo not here, jedoch nicht { false && true; }; echo herebeendet wird. Ich würde nicht set -emit einer Kahnstange anfassen und stattdessen die richtige Fehlerbehandlung durchführen.
Stéphane Chazelas
1

Ich vermute, wenn-dann-Bedingung als Ganzes als wahr zu bewerten.

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 von der if-Bedingung abgefangen, sodass die Bash das Ende der Ausführung nicht auslöst.

Archemar
quelle
Aber ich benutze nichtif ... fi
907
Ich weiß, das ist ein implizites wenn.
Archemar