Die genaue Sprache, die in der Single UNIX-Spezifikation zur Beschreibung der Bedeutung von verwendet wird,set -e
lautet:
Wenn diese Option aktiviert ist und ein einfacher Befehl aus einem der in Folgen von Shell-Fehlern aufgeführten Gründe fehlschlägt oder einen Beendigungsstatuswert> 0 zurückgibt und nicht [ein bedingter oder negierter Befehl] ist, wird die Shell sofort beendet.
Es besteht eine Unklarheit darüber, was passiert, wenn ein solcher Befehl in einer Subshell auftritt . Aus praktischer Sicht kann die Subshell nur beendet werden und einen Status ungleich Null an die übergeordnete Shell zurückgeben. Ob die übergeordnete Shell beendet wird, hängt davon ab, ob dieser Nicht-Null-Status zu einem einfachen Befehl führt, der in der übergeordneten Shell fehlschlägt.
Ein solcher problematischer Fall ist der, auf den Sie gestoßen sind: ein Rückgabestatus ungleich Null von einer Befehlsersetzung . Da dieser Status ignoriert wird, wird die übergeordnete Shell nicht beendet. Wie Sie bereits festgestellt haben , können Sie den Exit-Status berücksichtigen, indem Sie die Befehlsersetzung in einer einfachen Zuweisung verwenden : Der Exit-Status der Zuweisung ist der Exit-Status der letzten Befehlsersetzung in der (den) Zuweisung (en) .
Beachten Sie, dass dies nur dann wie vorgesehen ausgeführt wird, wenn es eine einzelne Befehlsersetzung gibt, da nur der Status der letzten Ersetzung berücksichtigt wird. Der folgende Befehl ist beispielsweise erfolgreich (sowohl gemäß dem Standard als auch in jeder Implementierung, die ich gesehen habe):
a=$(false)$(echo foo)
Ein weiterer Fall zu beachten gilt ist ausdrücklich Subshells : (somecommand)
. Gemäß der obigen Interpretation gibt die Subshell möglicherweise einen Status ungleich Null zurück. Da dies jedoch kein einfacher Befehl in der übergeordneten Shell ist, sollte die übergeordnete Shell fortgesetzt werden. Tatsächlich lassen alle mir bekannten Muscheln die Eltern zu diesem Zeitpunkt zurückkehren. Dies ist in vielen Fällen hilfreich, z. B. (cd /some/dir && somecommand)
wenn die Klammern verwendet werden, um einen Vorgang wie einen aktuellen Verzeichniswechsel lokal zu halten. Es verstößt jedoch gegen die Spezifikation, wenn set -e
in der Subshell deaktiviert ist oder wenn die Subshell auf eine Weise einen Nicht-Null-Status zurückgibt würde es nicht beenden, z. B. mit !
einem wahren Befehl. Zum Beispiel werden alle Befehle ash, bash, pdksh, ksh93 und zsh ohne Anzeige foo
in den folgenden Beispielen beendet:
set -e; (set +e; false); echo "This should be displayed"
set -e; (! true); echo "This should be displayed"
Doch kein einfacher Befehl ist fehlgeschlagen, solange er set -e
in Kraft war!
Ein dritter problematischer Fall sind Elemente in einer nichttrivialen Pipeline . In der Praxis ignorieren alle Shells Ausfälle der Elemente der Pipeline mit Ausnahme des letzten und zeigen in Bezug auf das letzte Pipelineelement eines von zwei Verhaltensweisen:
- ATT ksh und zsh, die das letzte Element der Pipeline in der übergeordneten Shell ausführen, verhalten sich wie gewohnt: Wenn ein einfacher Befehl im letzten Element der Pipeline fehlschlägt, führt die Shell diesen Befehl aus, der zufällig die übergeordnete Shell ist. Ausgänge.
- Andere Shells approximieren das Verhalten, indem sie beendet werden, wenn das letzte Element der Pipeline einen Status ungleich Null zurückgibt.
Wie zuvor set -e
bewirkt das Deaktivieren oder Verwenden einer Negation im letzten Element der Pipeline, dass der Status ungleich Null zurückgegeben wird, sodass die Shell nicht beendet wird. Andere Shells als ATT ksh und zsh werden dann beendet.
Die pipefail
Option von Bash bewirkt, dass eine Pipeline sofort beendet wird, set -e
wenn eines ihrer Elemente einen Nicht-Null-Status zurückgibt.
Beachten Sie, dass Bash als weitere Komplikation set -e
in Subshells deaktiviert wird, es sei denn, es befindet sich im POSIX-Modus ( set -o posix
oder POSIXLY_CORRECT
in der Umgebung, wenn Bash gestartet wird ).
All dies zeigt, dass die POSIX-Spezifikation bei der Angabe der -e
Option leider einen schlechten Job macht . Glücklicherweise sind die vorhandenen Muscheln in ihrem Verhalten größtenteils konsistent.