Gibt es eine Möglichkeit, ein Bash-Skript zu debuggen? ZB etwas, das eine Art Ausführungsprotokoll druckt, wie "Anrufzeile 1", "Anrufleitung 2" usw.
Gibt es eine Möglichkeit, ein Bash-Skript zu debuggen? ZB etwas, das eine Art Ausführungsprotokoll druckt, wie "Anrufzeile 1", "Anrufleitung 2" usw.
Antworten:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Diese geben Ihnen eine Spur von dem, was ausgeführt wird. (Siehe auch "Klarstellung" am Ende der Antwort.)
Manchmal müssen Sie das Debuggen innerhalb des Skripts steuern. In diesem Fall können Sie, wie Cheeto mich erinnerte , Folgendes verwenden:
set -x
Dies aktiviert das Debuggen. Sie können es dann wieder ausschalten mit:
set +x
(Sie können den aktuellen Ablaufverfolgungsstatus ermitteln, indem Sie $-
die aktuellen Flags analysieren x
.)
Außerdem bieten Shells im Allgemeinen die Optionen ' -n
' für 'keine Ausführung' und ' -v
' für den 'ausführlichen' Modus. Sie können diese in Kombination verwenden, um festzustellen, ob die Shell glaubt, dass sie Ihr Skript ausführen könnte - gelegentlich nützlich, wenn Sie irgendwo ein unausgeglichenes Zitat haben.
Es besteht die Behauptung, dass sich die -x
Option ' ' in Bash von anderen Shells unterscheidet (siehe Kommentare). Das Bash-Handbuch sagt:
-x
Drucken Sie eine Spur einfacher Befehle, for
Befehle, case
Befehle, select
Befehle und arithmetischer for
Befehle sowie deren Argumente oder zugehöriger Wortlisten, nachdem sie erweitert und ausgeführt wurden. Der Wert der PS4
Variablen wird erweitert und der resultierende Wert wird vor dem Befehl und seinen erweiterten Argumenten gedruckt.
Das scheint überhaupt kein anderes Verhalten anzuzeigen. Ich sehe keine anderen relevanten Verweise auf ' -x
' im Handbuch. Es werden keine Unterschiede in der Startsequenz beschrieben.
Erläuterung : Auf Systemen wie einer typischen Linux-Box, bei der ' /bin/sh
' ein Symlink zu ' /bin/bash
' ist (oder wo immer die ausführbare Bash-Datei gefunden wird), erzielen die beiden Befehlszeilen den gleichen Effekt wie das Ausführen des Skripts mit aktivierter Ausführungsablaufverfolgung. Auf anderen Systemen (z. B. Solaris und einigen moderneren Linux-Varianten) /bin/sh
ist Bash nicht vorhanden, und die beiden Befehlszeilen würden (geringfügig) unterschiedliche Ergebnisse liefern. Vor allem /bin/sh
würde ' ' durch Konstrukte in Bash verwirrt, die es überhaupt nicht erkennt. (Unter Solaris /bin/sh
handelt es sich um eine Bourne-Shell. Unter modernem Linux handelt es sich manchmal um Dash - eine kleinere, strengere POSIX-Shell.) Wenn der Name wie folgt aufgerufen wird, die 'shebang'-Zeile (' #!/bin/bash
'vs '#!/bin/sh
' '
Das Bash-Handbuch enthält einen Abschnitt zum Bash-POSIX-Modus , der im Gegensatz zu einer langjährigen, aber fehlerhaften Version dieser Antwort (siehe auch die folgenden Kommentare) den Unterschied zwischen "Bash aufgerufen als sh
" und "Bash aufgerufen als" ausführlich beschreibt bash
'.
Beim Debuggen eines (Bash-) Shell-Skripts ist es sinnvoll und vernünftig - sogar notwendig -, die in der Shebang-Zeile angegebene Shell mit der -x
Option zu verwenden. Andernfalls kann (wird?) Beim Debuggen ein anderes Verhalten auftreten als beim Ausführen des Skripts.
bash
Skript angegeben. Wenn Sie ein Bash-Skript mit sh -x
ausführen, verhält es sich völlig anders! Bitte aktualisieren Sie Ihre Antwort.
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Ich habe die folgenden Methoden verwendet, um mein Skript zu debuggen.
set -e
Lässt das Skript sofort anhalten, wenn ein externes Programm einen Exit-Status ungleich Null zurückgibt. Dies ist nützlich, wenn Ihr Skript versucht, alle Fehlerfälle zu behandeln, und wenn ein Fehler aufgetreten ist.
set -x
wurde oben erwähnt und ist sicherlich die nützlichste aller Debugging-Methoden.
set -n
Dies kann auch nützlich sein, wenn Sie Ihr Skript auf Syntaxfehler überprüfen möchten.
strace
ist auch nützlich, um zu sehen, was los ist. Besonders nützlich, wenn Sie das Skript nicht selbst geschrieben haben.
strace -f
erforderlich ist, wenn Sie auch Fehler in den vom Skript gestarteten Prozessen finden möchten. (was es um ein Vielfaches ausführlicher macht, aber dennoch nützlich ist, wenn Sie es auf die Syscalls beschränken, an denen Sie interessiert sind).
set -e
ist ... kontrovers .
Diese Antwort ist gültig und nützlich: https://stackoverflow.com/a/951352
Ich finde jedoch, dass die "Standard" -Skript-Debugging-Methoden ineffizient, nicht intuitiv und schwer zu verwenden sind. Für diejenigen, die an ausgefeilte GUI-Debugger gewöhnt sind, die alles zur Hand haben und die Arbeit für einfache Probleme zum Kinderspiel machen (und für schwierige Probleme möglich sind), sind diese Lösungen nicht sehr zufriedenstellend.
Ich verwende eine Kombination aus DDD und bashdb. Ersteres führt Letzteres aus, und Letzteres führt Ihr Skript aus. Dies bietet eine Benutzeroberfläche mit mehreren Fenstern die Möglichkeit, Code im Kontext zu durchlaufen und Variablen, Stapel usw. anzuzeigen, ohne die ständige mentale Anstrengung, den Kontext in Ihrem Kopf beizubehalten oder die Quelle immer wieder neu aufzulisten.
Hier finden Sie Anleitungen zum Einrichten: http://ubuntuforums.org/showthread.php?t=660223
Sie können auch "set -x" in das Skript schreiben.
Ich habe das Shellcheck-Dienstprogramm gefunden und vielleicht finden es einige Leute interessant https://github.com/koalaman/shellcheck
Ein kleines Beispiel:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
Beheben Sie den Fehler, versuchen Sie es zuerst ...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
Lass es uns erneut versuchen...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
jetzt finden!
Es ist nur ein kleines Beispiel.
Verwenden Sie Eclipse mit den Plugins Shelled & Basheclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Für geschälte: Laden Sie die Zip-Datei herunter und importieren Sie sie über die Hilfe in Eclipse -> Neue Software installieren: Lokales Archiv Für Basheclipse: Kopieren Sie die Gläser in das Dropins-Verzeichnis von Eclipse
Befolgen Sie die Schritte unter https://sourceforge.net/projects/basheclipse/files/?source=navbar
Ich habe ein Tutorial mit vielen Screenshots unter http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html geschrieben
Ich habe einen Bash-Debugger gebaut. Probieren Sie es einfach aus. Ich hoffe, es wird https://sourceforge.net/projects/bashdebugingbash helfen
setze + x = @ECHO AUS, setze -x = @ECHO EIN.
Sie können -xv
dem Standard-Shebang die folgende Option hinzufügen :
#!/bin/bash -xv
-x
: Zeigt Befehle und ihre Argumente an, während sie ausgeführt werden.
-v
: Shell-Eingabezeilen beim Lesen anzeigen.
ltrace
ist ein anderes Linux-Dienstprogramm ähnlich strace
. Allerdings ltrace
listet alle Bibliotheksaufrufe in einer ausführbaren Datei oder einem laufenden Prozess aufgerufen wird. Sein Name selbst stammt von der Verfolgung von Bibliotheksaufrufen. Beispielsweise:
ltrace ./executable <parameters>
ltrace -p <PID>
Ich denke, Sie können diesen Bash-Debugger ausprobieren: http://bashdb.sourceforge.net/ .
set -[nvx]
Zusätzlich zu
set -x
und
set +x
zum Stoppen der Müllkippe.
Ich möchte darüber sprechen, set -v
welcher Dump so klein wie weniger entwickelte Ausgabe ist.
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
Zum Testen einiger Variablen verwende ich manchmal Folgendes:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
zum Hinzufügen:
declare >&2 -p var1 var2
in Zeile 18 und Ausführen des resultierenden Skripts (mit Argumenten ), ohne sie bearbeiten zu müssen.
Dies könnte natürlich verwendet werden, um Folgendes hinzuzufügen set [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
wird declare -p v1 v2 >&2
nach Zeile 18, set -x
vor Zeile 22 und set +x
vor Zeile 26 hinzugefügt .
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
Hinweis: Sorgfalt über $LINENO
wird durch folgende Faktoren beeinträchtigt werden , on-the-fly Änderungen!
(Um das resultierende Skript ohne Ausführung zu sehen, lassen Sie es einfach fallen bash <(
und ) arg1 arg2
)
Schauen Sie sich meine Antwort zum Profilieren von Bash-Skripten an
Es gibt viele Details zur Protokollierung von Shell-Skripten über globale Shell-Variablen. Wir können die ähnliche Art der Protokollierung im Shell-Skript emulieren: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
Der Beitrag enthält Details zum Einführen von Protokollstufen wie INFO, DEBUG, ERROR. Verfolgungsdetails wie Skripteintrag, Skriptexit, Funktionseingang, Funktionsexit.
Beispielprotokoll: