Anzeigen der Zeilennummer beim Ausführen des Bash-Skripts

89

Ich habe ein Testskript, das viele Befehle enthält und viele Ausgaben generiert. Ich verwende set -xoder set -vund set -e, sodass das Skript angehalten wird, wenn ein Fehler auftritt. Es ist jedoch immer noch ziemlich schwierig für mich zu finden, in welcher Zeile die Ausführung gestoppt wurde, um das Problem zu lokalisieren. Gibt es eine Methode, die die Zeilennummer des Skripts ausgeben kann, bevor jede Zeile ausgeführt wird? Oder geben Sie die Zeilennummer vor der von set -x? Oder jede Methode, die sich mit meinem Problem mit der Position der Skriptzeile befassen kann, wäre eine große Hilfe. Vielen Dank.

dspjm
quelle

Antworten:

159

Sie erwähnen, dass Sie bereits verwenden -x. Die Variable gibt an, dass PS4der Wert die Eingabeaufforderung ist, die gedruckt wird, bevor die Befehlszeile wiedergegeben wird, wenn die -xOption festgelegt ist, und standardmäßig :Leerzeichen gefolgt werden.

Sie können die PS4Ausgabe ändern LINENO(Die Zeilennummer in der Skript- oder Shell-Funktion, die gerade ausgeführt wird).

Wenn Ihr Skript beispielsweise lautet:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

Wenn Sie es also ausführen, werden die Zeilennummern gedruckt:

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtips bietet das Ultimative PS4, das alles ausgibt, was Sie möglicherweise für die Ablaufverfolgung benötigen:

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
devnull
quelle
4
Ich frage mich, warum niemand dies für "Wie man Shell-Skripte debuggt?" Erwähnt. . Dies ist weitaus besser als nurecho
Suvarna Pattayil
@VusP Einverstanden, unnötige echoAussagen werden am besten vermieden.
devnull
2
Ich kann nicht umhin , das Gefühl , dass -x sollte Zeilennummern drucken. Oder vielleicht - nx sollte Zeilennummern enthalten. Für mich ist es einer dieser "WTF"
-Momente
1
Mann, ich wünschte, ich wüsste früher von dieser PS4-Erfindung ... Es hätte mir so viele Kopfschmerzen
erspart
2
\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'für einige Farben
Ulysse BN
34

$LINENOEnthält in Bash die Zeilennummer, in der das Skript gerade ausgeführt wird.

Wenn Sie die Zeilennummer kennen müssen, unter der die Funktion aufgerufen wurde, versuchen Sie es $BASH_LINENO. Beachten Sie, dass diese Variable ein Array ist.

Zum Beispiel:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

Sehen Sie hier für weitere Details der Bash Variablen.

Deqing
quelle
0

Einfache (aber leistungsstarke) Lösung: Platzieren Sie echoden Code, von dem Sie glauben, dass er das Problem verursacht, und verschieben Sie echoihn zeilenweise, bis die Meldungen nicht mehr auf dem Bildschirm angezeigt werden - da das Skript aufgrund eines vorherigen Fehlers gestoppt wurde.

Noch leistungsfähigere Lösung: Installieren Sie bashdbden Bash-Debugger und debuggen Sie das Skript Zeile für Zeile

hek2mgl
quelle
2
echoDas Herumspielen von Dingen kann in vielen Fällen hilfreich sein, ist jedoch unzureichend, wenn Sie versuchen, es in Funktionen anzuwenden, die eine aussagekräftige, analysierbare Ausgabe haben.
Eliran Malka
1
@EliranMalka Fairer Punkt. Sie können zu stderr in diesem Fall echo:echo "foo" >&2
hek2mgl
1
... sollte man in allen Fällen zu stderr zurückkehren , wenn der Zweck diagnostische Nachrichten sind.
Charles Duffy
0

Problemumgehung für Muscheln ohne LINENO

In einem ziemlich ausgefeilten Skript möchte ich nicht alle Zeilennummern sehen. Vielmehr möchte ich die Kontrolle über die Ausgabe haben.

Definieren Sie eine Funktion

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

Verwenden Sie es mit Anführungszeichen wie

echo_line_no "this is a simple comment with a line number"

Ausgabe ist

16   "this is a simple comment with a line number"

wenn die Nummer dieser Zeile in der Quelldatei 16 ist.

Dies beantwortet im Wesentlichen die Frage, wie die Zeilennummer angezeigt wird, wenn ein Bash-Skript für Benutzer von Asche oder anderen Shells ohne ausgeführt wird LINENO.

Möchten Sie noch etwas hinzufügen?

Sicher. Warum brauchst du das? Wie arbeitest du damit? Was können Sie damit machen? Ist dieser einfache Ansatz wirklich ausreichend oder nützlich? Warum willst du überhaupt daran basteln?

Möchten Sie mehr wissen? Lesen Sie die Überlegungen zum Debuggen

kklepper
quelle