Ich habe gerade mit bash gespielt, um die sommerliche Nachmittagshitze zu umgehen, als ich plötzlich ein mysteriöses Ergebnis habe, dessen Herkunft ich nicht bestimmen kann.
Lass es mich ein bisschen erklären.
Ich spiele mit Trap ERR, um einige Debugging-Funktionen für meine Bash-Skripte zu erstellen.
Dies ist das Skript, das gut läuft:
%Vor% Die Ausgabe ist (stderr geht zur besseren Übersicht auf /dev/null
; der bash-Fehler ist natürlich foo.sh: line 23: asdfas: command not found
, was so ist, wie Sie den Fehlercode 127 kennen)
Alle Zeilennummern sind rechts , Zeile 21 ist wo die Funktion "somefunction" startet und Zeile 24 ist wo sie aufgerufen wird.
Jedoch Wenn ich die erste Falle austrenne (die in main), bekomme ich diese Ausgabe:
%Vor%Falls ich die erste Falle auskommentiere und die zweite bemerke, bekomme ich, dass der Fehler in Zeile 23 ist, was auch richtig ist, weil es die absolute Zeile ist, wo der falsche Befehl platziert wird.
%Vor%Also meine Frage ist: Warum Linie 15? Woher kommt diese Zeilennummer? Zeile 15 ist die letzte Zeile in der Trap-Funktion. Kann jemand in einfachem Englisch erklären, warum Trap die letzte Zeile der Funktion zurückgibt, die es als die Zeile aufruft, die den Fehler in Zeile 21 erzeugte?
Vielen Dank im Voraus!
BEARBEITEN
Nur für den Fall, dass jemand an der Debug-Funktion interessiert ist. Dies ist die Produktionsversion:
%Vor%Was funktioniert wie:
%Vor%Einige relevante Fakten / Hintergrundinformationen:
Traps in ERR
werden nicht von Shell-Funktionen vererbt, obwohl sie den Rest der Umgebung erhalten, außer errtrace
ist gesetzt.
Der Exit-Status einer Funktion ist der des letzten Befehls.
Meine Vermutung, was passiert:
Wenn beide Traps aktiv sind,
ERR
-Falle in der Funktion aus. LINENO
ist die des nicht vorhandenen Befehls. ERR
-Falle in der Shell ausgelöst wird. LINENO
wird immer noch auf die letzte Zeile von traperror
gesetzt, da es die letzte auszuführende Zeile war und immer noch die aktuelle Zeile ist, da noch keine neue Zeile ausgeführt wurde. Wenn nur die Shell-Trap aktiv ist (der in der Funktion ist auskommentiert)
ERR
-Falle der Shell ausgelöst wird. Aus dem gleichen Grund oben ist LINENO
die letzte Zeile der Funktion, da sie die letzte auszuführende Zeile war und immer noch die aktuelle Zeile ist. Um sicherzustellen, dass in der ersten Version Ihrer traperror
-Funktion der Signalhandler ERR
nicht zweimal ausgeführt wird, können Sie den Signalhandler ERR
auf seine Standardaktion für den Rest Ihres Programms ignorieren oder zurücksetzen - innerhalb der Definition des Signalhandlers ERR
. Und dies sollte immer für einen benutzerdefinierten EXIT
-Signalhandler getan werden.