GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie finde ich die Zeilennummer in Bash, wenn ein Fehler aufgetreten ist?

Anstatt Ihre Funktion zu verwenden, würde ich stattdessen diese Methode verwenden:

$ cat yael.bash
#!/bin/bash

set -eE -o functrace

file1=f1
file2=f2
file3=f3
file4=f4

failure() {
  local lineno=$1
  local msg=$2
  echo "Failed at $lineno: $msg"
}
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR

cp -- "$file1" "$file2"
cp -- "$file3" "$file4"

Das funktioniert, indem man ERR abfängt und dann failure() aufruft Funktion mit der aktuellen Zeilennummer + dem ausgeführten Bash-Befehl.

Beispiel

Hier habe ich mich nicht um die Erstellung der Dateien gekümmert, f1 , f2 , f3 , oder f4 . Wenn ich das obige Skript ausführe:

$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"

Es schlägt fehl und meldet die Zeilennummer plus den ausgeführten Befehl.


Zusätzlich zu LINENO die aktuelle Zeilennummer enthalten, gibt es den BASH_LINENO und FUNCNAME (und BASH_SOURCE ) Arrays, die die Funktionsnamen und Zeilennummern enthalten, von denen sie aufgerufen werden.

Sie könnten also etwa so vorgehen:

#!/bin/bash

error() {
        printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
}

foo() {
        ( exit   0 ) || error "this thing"
        ( exit 123 ) || error "that thing"
}

foo

Wenn Sie das ausführen, wird gedruckt

'that thing' failed with exit code 123 in function 'foo' at line 9.

Wenn Sie set -e verwenden , oder trap ... ERR Um Fehler automatisch zu erkennen, beachten Sie, dass sie einige Einschränkungen haben. Es ist auch schwieriger, eine Beschreibung dessen einzufügen, was das Skript zu diesem Zeitpunkt tat (wie Sie es in Ihrem Beispiel getan haben), obwohl dies für einen normalen Benutzer nützlicher sein könnte als nur die Zeilennummer.

Siehe z.B. diese für die Probleme mit set -e und andere:

  • Warum funktioniert set -e nicht innerhalb von Subshells mit Klammern () gefolgt von einer ODER-Liste ||?
  • bash -e wird beendet, wenn let oder expr 0 ergibt
  • BashFAQ 105:Warum macht set -e (oder set -o errexit oder trap ERR) nicht das, was ich erwartet habe?

Bash hat eine eingebaute Variable $LINENO die in einer Anweisung durch die aktuelle Zeilennummer ersetzt wird, also können Sie das tun

in_case_fail $? "at $LINENO: cp $file1 $file2"

Sie können es auch mit trap ... ERR versuchen die ausgeführt wird, wenn ein Befehl fehlschlägt (wenn das Ergebnis nicht getestet wird). Beispiel:

trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR

Wenn dann ein Befehl wie cp $file1 $file2 schlägt fehl, erhalten Sie die Fehlermeldung mit der Zeilennummer und einem Exit. Sie finden den fehlerhaften Befehl auch in der Variablen $BASH_COMMAND (allerdings keine Umleitungen etc.).


Linux
  1. Wie finde ich die Anzahl der im Terminal verfügbaren vertikalen Linien?

  2. Wie werden Parameter eingestellt, wenn Bash-Skript an Bash übergeben wird?

  3. Wie liest man die vorletzte Zeile in einer Datei mit Bash?

  4. Wie kann ich die Anzahl der Benutzer online in Linux finden?

  5. Wie stelle ich die Farbe der Eingabeaufforderung in Bash ein?

So kommentieren Sie in Bash

So lesen Sie eine Datei Zeile für Zeile in Bash

So finden Sie die Portnummer eines Dienstes in Linux

So finden Sie heraus, wer das Linux-System wann neu gestartet hat

So finden Sie Dateien in der Ubuntu-Befehlszeile

Wie lösche ich die Zeilennummer in Vim beim Kopieren?