Gibt es eine Möglichkeit, ein Bash-Skript zu debuggen? ZB etwas, das eine Art Ausführungsprotokoll wie "Aufrufende Zeile 1", "Aufrufende Zeile 2" usw. ausgibt.
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 Debugging im Skript steuern. In diesem Fall können Sie, wie Cheetodaran erinnert mich, Folgendes verwenden:
set -x
Dadurch wird das Debuggen aktiviert. Sie können es dann wieder ausschalten mit:
set +x
(Sie können den aktuellen Ablaufverfolgungsstatus ermitteln, indem Sie $-
, die aktuellen Flags, für x
analysieren.)
Außerdem bieten Shells im Allgemeinen die Optionen '-n
' für 'keine Ausführung' und '-v
' für den 'verbose' -Modus. Sie können diese in Kombination verwenden, um zu prüfen, ob die Shell der Meinung ist, dass sie Ihr Skript ausführen könnte. Dies kann gelegentlich nützlich sein, wenn Sie ein unausgewogenes Angebot haben.
Es besteht die Behauptung, dass die '-x
'-Option in Bash sich von anderen Shells unterscheidet (siehe die Kommentare). Das Bash Manual sagt:
-x
Drucken Sie eine Spur von einfachen Befehlen, for
-Befehlen, case
-Befehlen, select
-Befehlen und arithmetischen for
-Befehlen sowie deren Argumenten oder zugehörigen Wortlisten, nachdem sie erweitert wurden und bevor sie ausgeführt werden. Der Wert der PS4
-Variablen wird erweitert und der resultierende Wert wird vor dem Befehl und seinen erweiterten Argumenten gedruckt.
So viel scheint überhaupt kein anderes Verhalten zu sein. Ich sehe keine weiteren relevanten Verweise auf '-x
' im Handbuch. Unterschiede in der Startreihenfolge werden nicht beschrieben.
Clarification: Auf Systemen wie einer typischen Linux-Box, bei denen '/bin/sh
' ein Symlink zu '/bin/bash
' ist (oder wo immer die ausführbare Datei von Bash gefunden wird), erzielen die beiden Befehlszeilen den gleichen Effekt, wenn das Skript mit Ausführung ausgeführt wird weiter verfolgen. Auf anderen Systemen (z. B. Solaris und einigen moderneren Linux-Varianten) ist /bin/sh
kein Bash, und die beiden Befehlszeilen führen zu (etwas) unterschiedlichen Ergebnissen. Insbesondere wird '/bin/sh
' von Konstrukten in Bash verwirrt, die es überhaupt nicht erkennt. (Unter Solaris ist /bin/sh
eine Bourne-Shell; unter modernen Linux ist dies manchmal Dash - eine kleinere, strengere POSIX-Shell.) Wenn der Name mit diesem Namen aufgerufen wird, ist die Zeile 'Shebang' ('#!/bin/bash
' vs. '#!/bin/sh
') am Anfang der Datei hat keine Auswirkung auf die Interpretation des Inhalts.
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 Kommentare unten) den Unterschied zwischen 'Bash als sh
' ausführlich beschreibt. und 'Bash als bash
aufgerufen'.
Beim Debuggen eines (Bash) Shell-Skripts ist es sinnvoll und vernünftig - sogar notwendig -, die in der Shebang-Zeile angegebene Shell mit der Option -x
zu verwenden. Andernfalls können Sie (werden?) Beim Debuggen ein anderes Verhalten erhalten als beim Ausführen des Skripts.
Ich habe die folgenden Methoden verwendet, um mein Skript zu debuggen.
set -e
stoppt das Skript sofort, 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 auftreten sollte.
set -x
wurde oben erwähnt und ist sicherlich die nützlichste Debugging-Methode.
set -n
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.
Diese Antwort ist gültig und nützlich: https://stackoverflow.com/a/951352
Ich finde jedoch, dass die Debugging-Methoden des "Standard" -Skripts ineffizient, nicht intuitiv und schwer zu verwenden sind. Für diejenigen, die an anspruchsvolle GUI-Debugger gewöhnt sind, die Ihnen alles zur Verfügung stellen und die Arbeit für leichte Probleme (und für schwierige Probleme möglich) zum Kinderspiel machen, sind diese Lösungen nicht sehr zufriedenstellend.
Was ich mache, ist 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 mit der Möglichkeit, Code in Kontext zu durchlaufen und Variablen, Stapel usw. anzuzeigen, ohne den ständigen mentalen Aufwand, den Kontext in Ihrem Kopf zu behalten oder die Quelle immer wieder aufzulisten.
Es gibt Richtlinien, wie man das hier einrichten kann: http://ubuntuforums.org/showthread.php?t=660223
Sie können auch "set -x" innerhalb des Skripts schreiben.
Ich habe ein Shellcheck-Hilfsprogramm gefunden, und einige Leute finden es 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.
den Fehler beheben, zuerst versuchen ...
$ 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.
Ich habe einen Bash-Debugger gebaut. Probieren Sie es einfach aus. Ich hoffe es hilft https://sourceforge.net/projects/bashdebugingbash
Ich denke, Sie können diesen Bash-Debugger ausprobieren: http://bashdb.sourceforge.net/ .
set + x = @ECHO OFF, setze -x = @ECHO ON.
Sie können die -xv
-Option wie folgt zum Standard-Shebang hinzufügen:
#!/bin/bash -xv
-x
: Zeigt Befehle und ihre Argumente an, während sie ausgeführt werden.-v
: Zeigt Shell-Eingabezeilen an, wenn sie gelesen werden.
ltrace
ist ein weiteres Linux-Dienstprogramm, das strace
ähnlich ist. ltrace
listet jedoch alle Bibliotheksaufrufe auf, die in einer ausführbaren Datei oder einem laufenden Prozess aufgerufen werden. Der Name selbst stammt von der Anrufverfolgung in der Bibliothek. Zum Beispiel:
ltrace ./executable <parameters>
ltrace -p <PID>
set -[nvx]
verwendenZusätzlich zu
set -x
und
set +x
zum Stoppen der Müllkippe.
Ich möchte über set -v
sprechen, der als kleiner als weniger entwickelte Ausgabe abläuft.
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
Um einige Variablen zu testen, verwende ich manchmal Folgendes:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
zum Hinzufügen von:
declare >&2 -p var1 var2
in Zeile 18 und Ausführen des resultierenden Skripts (mit args), ohne dass sie bearbeitet werden müssen.
natürlich könnte dies zum Hinzufügen von set [+-][nvx]
verwendet werden:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
fügt declare -p v1 v2 >&2
nach Zeile 18, set -x
vor Zeile 22 und set +x
vor Zeile 26 ein.
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo [email protected], $((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: Die Beachtung von $LINENO
wird von on-the-fly Modifikationen beeinflusst!
(Um das resultierende Skript anzuzeigen, ohne es auszuführen, lassen Sie einfach bash <(
und ) arg1 arg2
fallen.)
Werfen Sie einen Blick auf meine Antwort zum Profilieren von Bash-Skripten
Die Protokollierung von Shell-Skripts über globale Variablen von Shell bietet viele Details. Wir können eine ähnliche Art der Protokollierung in einem Shell-Skript emulieren: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-Shell-scripts.html
Der Beitrag enthält Details zum Protokollieren von Protokollen wie INFO, DEBUG, ERROR . Tracing-Details wie Skripteintrag, Skript-Exit, Funktionseintrag, Funktionsexit.
Beispielprotokoll:
Benutze Eclipse mit geschälten Plugins & Basheclipse.
https://sourceforge.net/projects/shelled/?source=directoryhttps://sourceforge.net/projects/basheclipse/?source=directory
Für Shelled: Laden Sie die ZIP-Datei herunter und importieren Sie sie in Eclipse über Hilfe -> Neue Software installieren: lokales Archiv Für Basheclipse: Kopieren Sie die Jars in das Dropins-Verzeichnis von Eclipse
Befolgen Sie die Anweisungen unter https://sourceforge.net/projects/basheclipse/files/?source=navbar
Ich habe ein Tutorial mit vielen Screenshots geschrieben unter http://dietrichschroff.blogspot.de/2017/07/bash-enabling-Eclipse-for-bash.html