Ein Punkt, der in den vorhandenen Antworten fehlt, ist die Vererbung der Fehlerfallen. Die bash
Shell bietet eine solche Option für die Verwendung von set
-E
Wenn sie aufgestellt ist, wird jede Falle auf ERR
wird an Shell-Funktionen, Befehlssubstitutionen und Befehle vererbt, die in einer Subshell-Umgebung ausgeführt werden. Die ERR
Falle ist normalerweise no in solchen Fällen vererbt.
Adam Rosenfields Antwort Empfehlung zur Verwendung set -e
ist in bestimmten Fällen richtig, hat aber seine eigenen potenziellen Fallstricke. Siehe GreyCat's BashFAQ - 105 - Warum macht set -e (oder set -o errexit, oder trap ERR) nicht das, was ich erwartet habe?
Dem Handbuch zufolge verlässt set -e
wenn ein einfacher Befehl mit einem Status ungleich Null beendet wird. Die Shell wird nicht beendet, wenn der fehlgeschlagene Befehl Teil der Befehlsliste ist, die unmittelbar auf einen while
o until
Schlüsselwort, Teil der test in a if statement
, Teil eines &&
o ||
Liste mit Ausnahme des Befehls nach dem final && or ||
, any command in a pipeline but the last
oder wenn der Rückgabewert des Befehls über !
".
was bedeutet, set -e
funktioniert in den folgenden einfachen Fällen nicht (detaillierte Erklärungen finden Sie im Wiki)
-
Verwendung des arithmetischen Operators let
o $((..))
( bash
4.1 ff), um einen Variablenwert zu erhöhen als
#!/usr/bin/env bash
set -e
i=0
let i++ # or ((i++)) on bash 4.1 or later
echo "i is $i"
-
Wenn der beanstandete Befehl no Teil des letzten Befehls, der über &&
o ||
. Zum Beispiel würde die folgende Falle nicht auslösen, wenn sie es sollte
#!/usr/bin/env bash
set -e
test -d nosuchdir && echo no dir
echo survived
-
Bei falscher Verwendung in einer if
Anweisung als, der Exit-Code der if
Anweisung ist der Exit-Code des zuletzt ausgeführten Befehls. Im folgenden Beispiel war der zuletzt ausgeführte Befehl echo
die die Falle nicht auslösen würde, obwohl die test -d
gescheitert
#!/usr/bin/env bash
set -e
f() { if test -d nosuchdir; then echo no dir; fi; }
f
echo survived
-
Bei der Verwendung mit Befehlssubstitution werden sie ignoriert, es sei denn inherit_errexit
wird eingestellt mit bash
4.4
#!/usr/bin/env bash
set -e
foo=$(expr 1-1; true)
echo survived
-
wenn Sie Befehle verwenden, die wie Zuweisungen aussehen, aber keine sind, wie z. B. export
, declare
, typeset
o local
. Hier der Funktionsaufruf an f
sera no Ausgang als local
hat den zuvor eingestellten Fehlercode gekehrt.
set -e
f() { local var=$(somecommand that fails); }
g() { local var; var=$(somecommand that fails); }
-
Wenn der Befehl in einer Pipeline verwendet wird und der verletzende Befehl no Teil des letzten Befehls. So würde z.B. der unten stehende Befehl trotzdem ausgeführt werden. Eine Möglichkeit ist die Aktivierung von pipefail
durch Rückgabe des Exit-Codes der erste gescheiterten Prozess:
set -e
somecommand that fails | cat -
echo survived
Die ideale Empfehlung lautet no verwenden. set -e
und implementieren Sie stattdessen eine eigene Version der Fehlerprüfung. Weitere Informationen zur Implementierung einer eigenen Fehlerbehandlung finden Sie in einer meiner Antworten auf Fehler in einem Bash-Skript auslösen
2 Stimmen
Die Antwort geht an Adam für die Details zu set -e (was genau erwünscht ist). Dank auch an a_m0d für die Info über Fallen (obwohl nicht 100% relevant).
2 Stimmen
Gelten diese Antworten für
sh
genau so wiebash
?