Ich versuche, eine Fehlerberichterstattung mit einer Trap zu erstellen, um eine Funktion für alle Fehler aufzurufen:
Trap "_func" ERR
Ist es möglich zu erfahren, von welcher Leitung das ERR-Signal gesendet wurde? Die Muschel ist bash.
In diesem Fall kann ich lesen und melden, welcher Befehl verwendet wurde, und einige Aktionen protokollieren / ausführen.
Oder mache ich das vielleicht falsch?
Ich habe mit folgendem getestet:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
Und $LINENO
kehrt zurück 2. Funktioniert nicht.
bash
shell-script
error-handling
trap
Mechaflash
quelle
quelle
bashdb
. Es scheint, dass das erste Argumenttrap
Variablen enthalten kann, die im gewünschten Kontext ausgewertet werden. Sollte alsotrap 'echo $LINENO' ERR'
funktionieren.trap 'echo $LINENO' ERR
. Das erste Argumenttrap
ist das gesamteecho $LINENO
hart zitierte. Das ist in Bash.trap 'echo $LINENO' ERR
, mit einfachen Anführungszeichen, keine doppelten Anführungszeichen. Mit dem Befehl , den Sie geschrieben,$LINENO
erweitert wird , wenn Leitung 2 analysiert wird, so dass der Fall istecho 2
(oder besser gesagtECHO 2
, die ausgeben würdebash: ECHO: command not found
).Antworten:
Wie in den Kommentaren erwähnt, ist Ihr Zitat falsch. Sie benötigen einfache Anführungszeichen, um zu verhindern,
$LINENO
dass sie beim ersten Analysieren der Überfüllungslinie erweitert werden.Das funktioniert:
Laufen es:
quelle
echo hello | grep foo
scheint keinen Fehler für mich zu werfen. Verstehe ich etwas falsch?grep
hat ein Exit-Status von 0, wenn es eine Übereinstimmung gab, 1, wenn es keine Übereinstimmung gab und> 1 für einen Fehler. Sie können das Verhalten auf Ihrem System mitecho hello | grep foo; echo $?
Sie können auch den eingebauten Bash-Aufrufer verwenden:
es gibt auch den Dateinamen aus:
quelle
Mir gefällt die Antwort von @Mat sehr gut. Darauf aufbauend habe ich einen kleinen Helfer geschrieben, der dem Fehler etwas mehr Kontext verleiht:
Wir können das Skript auf die Zeile untersuchen, die den Fehler verursacht hat:
Hier ist es in einem kleinen Testskript:
Wenn wir es ausführen, erhalten wir:
quelle
$(caller)
wenn Sie die Daten von verwenden, um den Kontext anzugeben, auch wenn der Fehler nicht im aktuellen Skript, sondern in einem seiner Importe liegt. Aber sehr schön!Inspiriert von einer anderen Antwort ist hier eine einfachere kontextbezogene Fehlerbehandlung:
Bei Bedarf können Sie auch awk anstelle von tail & head verwenden .
quelle
Hier ist eine andere Version, inspiriert von @sanmai und @unpythonic. Es werden Skriptzeilen mit Zeilennummern und dem Exit-Status um den Fehler herum angezeigt - mit tail & head scheint dies einfacher zu sein als mit der awk-Lösung.
Aus Gründen der Lesbarkeit werden hier zwei Zeilen angezeigt. Sie können diese Zeilen zu einer verbinden, wenn Sie dies bevorzugen (unter Beibehaltung der
;
):Dies funktioniert sehr gut mit
set -euo pipefail
( inoffizieller Strict-Modus ) - jeder undefinierte Variablenfehler gibt eine Zeilennummer ohne dasERR
Pseudosignal auszulösen, aber die anderen Fälle zeigen den Kontext.Beispielausgabe:
quelle
Ja,
LINENO
undBASH_LINENO
Variablen sind nützlich, um die Fehlerlinie und die dazu führenden Linien zu ermitteln.Nein, nur fehlende
-q
Option mit grep ...... Mit der
-q
Optiongrep
wird0
fürtrue
und1
für zurückkehrenfalse
. Und in Bash ist estrap
nichtTrap
...Hier ist ein Trapper, der nützlich sein könnte, um Dinge zu debuggen, die eine etwas zyklomatischere Komplexität haben ...
failure.sh
... und ein Beispiel für ein Verwendungsskript, um die subtilen Unterschiede beim Setzen der obigen Falle für die Funktionsverfolgung aufzudecken ...
example_usage.sh
Das oben Gesagte wurde mit Bash Version 4+ getestet. Hinterlassen Sie daher einen Kommentar, wenn Versionen vor vier erforderlich sind, oder eröffnen Sie ein Problem, wenn Fehler auf Systemen mit einer Mindestversion von vier nicht abgefangen werden können.
Die wichtigsten Imbissbuden sind ...
-E
bewirkt, dass Fehler innerhalb von Funktionen in die Luft sprudeln-o functrace
Ursachen ermöglichen mehr Ausführlichkeit, wenn etwas innerhalb einer Funktion fehlschlägtUm Funktionsaufrufe werden einfache Anführungszeichen und um einzelne Argumente doppelte Anführungszeichen verwendet
Verweise auf
LINENO
undBASH_LINENO
werden anstelle der aktuellen Werte übergeben, obwohl dies in späteren Versionen von "Linked to Trap" möglicherweise verkürzt wird, sodass die endgültige Fehlerzeile es zur Ausgabe machtDie Werte von
BASH_COMMAND
und exit status ($?
) werden übergeben, um erstens den Befehl abzurufen, der einen Fehler zurückgegeben hat, und zweitens, um sicherzustellen, dass der Trap nicht bei fehlerfreien Zuständen ausgelöst wirdUnd während andere anderer Meinung sein mögen, finde ich es einfacher, ein Ausgabe-Array zu erstellen und printf zum Drucken jedes Array-Elements in einer eigenen Zeile zu verwenden ...
... auch das
>&2
Bit am Ende bringt Fehler dahin, wo sie hin sollen (Standardfehler) und ermöglicht das Erfassen nur von Fehlern ...Wie diese und andere Beispiele zu Stack Overflow zeigen, gibt es viele Möglichkeiten, eine Debugging-Hilfe mithilfe integrierter Dienstprogramme zu erstellen.
quelle