Wie kann verhindert werden, dass ein Befehl eine ERR-Trap auslöst?

Wie kann verhindert werden, dass ein Befehl eine ERR-Trap auslöst?

Ich verwende eine ERR-Trap, um alle Fehler in meinem Bash-Skript abzufangen und im Protokoll auszugeben, was passiert ist. (ähnlich dieser Frage:Trap, ERR und Echo der Fehlerzeile) Es funktioniert wie erwartet. Das einzige Problem ist, dass an einem bestimmten Punkt in meinem Skript ein Exitcode !=0 erwartet wird. Wie kann ich dafür sorgen, dass die Falle in dieser Situation nicht ausgelöst wird?

Hier ist ein Teil des Codes:

err_report() {
    echo "errexit on line $(caller)" | tee -a $LOGFILE 1>&2
}

trap err_report ERR

Dann später im Skript:

<some command which occasionally will return a non-zero exit code>

if [ $? -eq 0 ]; then
    <handle stuff>
fi

Jedes Mal, wenn der Befehl einen Wert ungleich Null zurückgibt, wird meine Falle ausgelöst. Kann ich dies nur für diesen Teil des Codes vermeiden?

Ich habe diese Frage überprüft:Korrektes Verhalten von EXIT- und ERR-Traps bei Verwendung von `set -eu` aber ich verstehe nicht wirklich, wie ich es auf meinen Fall anwenden kann – sofern es überhaupt anwendbar ist.

Antwort1

Ein ERR trapwird nicht ausgelöst, wenn ein Fehlercode sofort "abgefangen" wird, was bedeutet, dass Siedürfenuse if-Anweisungen und so weiter, ohne die Fehlerabfangfunktion ständig ein- und ausschalten zu müssen. Siekann nichtVerwenden Sie die Überprüfung $?zur Flusssteuerung, da der nicht abgefangene Fehler zu dem Zeitpunkt, an dem Sie zu dieser Überprüfung gelangen, möglicherweise bereits vorliegt.

Wenn Sie einen Befehl haben, von dem Sie erwarten, dass er fehlschlägt - und SienichtWenn Sie möchten, dass diese Fehler die auslösen trap, müssen Sie den Fehler einfach abfangen. Sie in eine ifAnweisung einzubinden ist umständlich und langatmig, aber diese Kurzform funktioniert gut:

/bin/false || :  # will not trigger an ERR trap

Wenn Sie jedoch etwas unternehmen möchten, wenn ein Befehl fehlschlägt, ifist Folgendes kein Problem:

if ! /bin/false; then
    echo "this was not caught by the trap!"
fi

Alternativ elsewird der Fehlerzustand auch abgefangen durch:

if /bin/false; then
    : # dead code
else
    echo "this was not caught by the trap!"
fi

Zusammengefasst: set -eund trap "command" ERRwerden nur dann ausgelöst, wenn ein Fehlerzustand vorliegt, der nicht unmittelbar und intrinsisch erklärt werden kann.

Antwort2

ERRSie können die Falle während Teilen Ihres Codes nach Bedarf aktivieren/deaktivieren .

#!/bin/bash
err_report() {
    echo "errexit on line $(caller)"
}
trap err_report ERR
trap - ERR             # disable ERR trap
false
if [ $? -eq 0 ]; then
    printf "OK\n"
else
    printf "FAIL\n"    # prints FAIL
fi
trap err_report ERR    # enable ERR trap
false                  # prints errexit on line 14

Antwort3

Ich stelle fest, dass ich häufig ERR-Fallen vermeiden möchte, aber ich möchte auch den Rückgabecode meiner Funktion nicht verwerfen. Daher verwende ich folgendes Muster:

RC=0
some_function || RC=$?

Dann mache ich mit RC, was immer ich machen muss.

Antwort4

Die ERRFalle unterliegt denselben Regeln wie set -e, das heißt, sie wirkt sich nicht auf Befehle aus, die als Bedingungen verwendet werden.

trap "echo error" ERR
false                     # this should trigger the trap
if ! false; then          # this shouldn't
     echo handle stuff
fi

Beachten Sie, dass der Befehl in der ifBedingungbeliebigBefehl, es muss nicht sein [ .. ]. Wenn Sie also nur eine True/False-Auswertung des Beendigungsstatus eines Befehls wünschen, verwenden Sie es einfach direkt in der ifBedingung.

Wenn Sie den Exit-Code speichern müssenUndUm der ERRFalle auszuweichen, müssen Sie etwas tun wie

somecmd && :; ret=$?

Hier &&wird die Falle beseitigt ERR, aber da sie nur ausgeführt wird, wenn der Exit-Code Null ist, wissen wir, dass der Exit-Code nach derselbe ist :.

Vielleicht möchten Sie überprüfenBashFAQ 105: Warum bewirkt set -e (oder set -o errexit oder trap ERR) nicht das, was ich erwartet habe?

verwandte Informationen