Ich beobachte ein seltsames Verhalten, wenn ich set -e
( errexit
), set -u
( nounset
) zusammen mit ERR- und EXIT-Traps verwende. Sie scheinen verwandt zu sein, daher erscheint es vernünftig, sie in eine Frage zu stellen.
1) set -u
löst keine ERR-Traps aus
Code:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}
- Erwartet: ERR-Trap wird aufgerufen, RC! = 0
- Aktuell: ERR-Trap wird nicht aufgerufen, RC == 1
- Hinweis:
set -e
Ändert das Ergebnis nicht
2) Bei Verwendung set -eu
des Exit-Codes in einem EXIT-Trap ist 0 anstelle von 1
Code:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}
- Erwartet: EXIT-Trap wird aufgerufen, RC == 1
- Aktuell: EXIT-Trap wird aufgerufen, RC == 0
- Hinweis: Bei Verwendung von
set +e
RC == 1. Der EXIT-Trap gibt den richtigen RC zurück, wenn ein anderer Befehl einen Fehler ausgibt. - Bearbeiten: Es gibt einen SO-Beitrag zu diesem Thema mit einem interessanten Kommentar, der darauf hinweist , dass dies möglicherweise mit der verwendeten Bash-Version zusammenhängt. Das Testen dieses Snippets mit Bash 4.3.11 ergibt eine RC = 1, das ist also besser. Ein Upgrade von Bash (von 3.2.51) auf alle Hosts ist derzeit leider nicht möglich, daher müssen wir uns eine andere Lösung einfallen lassen.
Kann jemand eines dieser Verhalten erklären?
Das Durchsuchen dieser Themen war nicht sehr erfolgreich, was angesichts der Anzahl der Posts zu Bash-Einstellungen und -Fallen eher überraschend ist. Es gibt zwar einen Forenthread , aber das Fazit ist eher unbefriedigend.
set -e
und set -u
beide wurden speziell entwickelt, um eine Skript-Shell zu töten . Mit ihnen unter Bedingungen , die ihre Anwendung auslösen könnten wird töten eine Skript Shell. Daran führt kein Weg vorbei, außer sie nicht zu verwenden und stattdessen auf diese Bedingungen zu testen , wenn sie in einer Codesequenz angewendet werden. Grundsätzlich können Sie also guten Shell-Code schreiben oder verwenden set -eu
.
-u
die ERR-Falle nicht ausgelöst werden sollte (es ist ein Fehler, sollte es also nicht die Falle auslösen) oder der Fehlercode 0 statt 1 ist Letzteres scheint ein Fehler zu sein, der bereits in einer späteren Version behoben wurde. Der erste Teil ist jedoch schwer zu verstehen, wenn Sie nicht bemerkt haben, dass Fehler in der Shell-Auswertung (Parametererweiterung) und tatsächliche Fehler in Befehlen zwei verschiedene Dinge zu sein scheinen. Wie Sie vorgeschlagen haben, versuche ich jetzt, die Lösung zu vermeiden -eu
und manuell zu überprüfen, ob sie erforderlich ist.
(set -u; : $UNSET_VAR)
und ähnliches lokalisiert werden kann . Diese Art von Zeug kann auch gut sein - Sie können &&
gelegentlich eine Menge davon fallen lassen:, (set -e; mkdir dir; cd dir; touch dirfile)
wenn Sie meinen Drift bekommen. Es ist nur so, dass dies kontrollierte Kontexte sind - wenn Sie sie als globale Optionen festlegen, verlieren Sie die Kontrolle und werden kontrolliert. In der Regel gibt es jedoch effizientere Lösungen.
bash
der Standard gebrochen und Fallen in Unterschalen gelegt. Die Falle soll in derselben Umgebung ausgeführt werden, aus der die Rückgabe kam,bash
hat dies aber seit einiger Zeit nicht mehr getan.