it-swarm.com.de

Wie debuggen Sie ein Bash-Skript?

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.

147
corvus
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.

183

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.

27
FD Gonthier

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

12
Stabledog

Sie können auch "set -x" innerhalb des Skripts schreiben.

9
Cheeto

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.

8
Equation Solver

Ich habe einen Bash-Debugger gebaut. Probieren Sie es einfach aus. Ich hoffe es hilft https://sourceforge.net/projects/bashdebugingbash

2
abadjm

Installieren Sie VSCode , fügen Sie dann die Erweiterung bash debug hinzu und Sie können im visuellen Modus debuggen. siehe Hier in Aktion.

 enter image description here

2
yantaq

Ich denke, Sie können diesen Bash-Debugger ausprobieren: http://bashdb.sourceforge.net/ .

1
Nan Xiao

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>  

Quelle

1
Premraj

Einige Tricks zum Debuggen von bash scripts:

set -[nvx] verwenden

Zusä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

Dump-Variablen oder Ablaufverfolgung fliegend

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.

kleine probe:

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.)

Schritt für Schritt zur Ausführungszeit

Werfen Sie einen Blick auf meine Antwort zum Profilieren von Bash-Skripten

0
F. Hauri

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:

 enter image description here

0
Piyush Chordia

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

 enter image description here

Ich habe ein Tutorial mit vielen Screenshots geschrieben unter http://dietrichschroff.blogspot.de/2017/07/bash-enabling-Eclipse-for-bash.html

0