Wie kann man ein Bash-Skript debuggen?

135

Ich habe einige Probleme mit einigen Skripten in Bash, über Fehler und unerwartetes Verhalten. Ich möchte die Ursachen der Probleme untersuchen, damit ich Korrekturen anwenden kann. Gibt es eine Möglichkeit, eine Art "Debug-Modus" für Bash zu aktivieren, um weitere Informationen zu erhalten?

Braiam
quelle

Antworten:

132

Starten Sie Ihr Bash-Skript mit bash -x ./script.shoder fügen Sie es hinzu set -x, um die Debug-Ausgabe zu sehen.


Zusätzlich mit bash4.1 oder neuer:

Wenn Sie die Debug-Ausgabe in eine separate Datei schreiben möchten, fügen Sie dies Ihrem Skript hinzu:

exec 5> debug_output.txt
BASH_XTRACEFD="5"

Siehe: https://stackoverflow.com/a/25593226/3776858


Wenn Sie die Zeilennummern sehen möchten, fügen Sie Folgendes hinzu:

PS4='$LINENO: '


Wenn Sie Zugriff auf den loggerBefehl haben, können Sie hiermit die Debug-Ausgabe über Ihr Syslog mit Zeitstempel, Skriptname und Zeilennummer schreiben:

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here

Sie können Option -pdes loggerBefehls eine individuelle Einrichtung und Pegel einzustellen Ausgabe über lokale syslog auf seine eigene Logfile zu schreiben.

Cyrus
quelle
7
-v kann auch helfen (druckt jede Zeile aus, wenn sie ausgeführt wird. Kann mit -x kombiniert werden). Und siehe auch: bashdb.sourceforge.net
Olivier Dulac
4
Eine weitere wunderbare Ressource ist: shellcheck.net
Olivier Dulac
Was macht "exec 5>"?
Aggsol
3
@aggsol: Wenn Sie BASH_XTRACEFD="5"bash schreibt die Trace - Ausgabe erzeugt , wenn set -xaktiviert wird Deskriptordatei 5. exec 5> >(logger -t $0)Descriptor leitet die Ausgabe von Datei 5 zu loggerBefehl.
Cyrus
1
Nur fragen, können Sie Zeilennummer und Shell-Skript Pfad oder Name in PS4 bekommen?
iloveretards
55

Verwenden set -x

Ich benutze immer set -xund set +x. Sie können Bereiche, die Sie sehen möchten, umbrechen, um die Ausführlichkeit zu erhöhen / zu verringern.

#!/bin/bash

set -x
..code to debug...
set +x

log4bash

Auch wenn Sie Entwicklungsarbeit geleistet haben und mit dem Stil der Logger unter den Namen log4j, log4perl usw. vertraut sind, sollten Sie log4bash verwenden .

Auszug

Seien wir ehrlich - einfaches altes Echo schneidet es einfach nicht. log4bash ist ein Versuch, Bash-Skripte besser zu protokollieren (dh, die Protokollierung in Bash ist nicht so einfach).

Von dort aus können Sie in Ihren Bash-Skripten Folgendes tun:

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Ergebnis dieser Art von Ausgabe:

    ss1

log4sh

Wenn Sie etwas Tragbareres brauchen, gibt es auch das Ältere log4sh. Arbeiten ähnlich wie log4bashhier erhältlich:

slm
quelle
Auf Ubuntu habe ich alias say="spd-say"in meiner .bashrc, die den sayBefehl aus anderen Distributionen oder OS X imitiert.
Doorknob
1
set -vx wäre eine gute Kombination, wenn es mit trap - trap read debug verwendet wird. Auf diese Weise können Sie Zeile für Zeile
übergehen
34

Es gibt einen Bash-Debugger, bashdb , der auf vielen Distributionen installiert werden kann. Es verwendet den integrierten erweiterten Debugging-Modus von bash ( shopt -s extdebug). Es sieht sehr nach gdb aus; Hier ist eine Beispielsitzung, um etwas Geschmack zu geben:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf

Wie in gdb wird die Anweisung kurz vor ihrer Ausführung angezeigt . So können wir Variablen untersuchen, um zu sehen, was die Anweisung tun wird, bevor sie es tut.

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG

Das wollen wir nicht! Schauen wir uns noch einmal die Parametererweiterung an.

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg

OK, das funktioniert. Stellen wir newfden richtigen Wert ein.

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

Sieht gut aus. Setzen Sie das Skript fort.

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg
Mark Plotnick
quelle
20

Die Standardmethode zum Debuggen von Skripten in den meisten Bourne-basierten Shells, wie z. B. Bash, ist das Schreiben set -xam oberen Rand Ihres Skripts. Dies macht bash ausführlicher darüber, was getan / ausgeführt wird und wie Argumente ausgewertet werden.

-x  Print commands and their arguments as they are executed.

Dies ist entweder für den Interpreter oder für interne Skripte nützlich. Zum Beispiel:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory

Oben sehen wir, warum der Suchvorgang aufgrund einzelner Anführungszeichen fehlschlägt.

Um die Funktion zu deaktivieren, geben Sie einfach ein set +x.

Braiam
quelle
13

Eclipse verwenden

Sie können die kombinierte Umgebung von Eclipse und Shelled mit dem unten verlinkten Skript "_DEBUG.sh" verwenden.

Muscheln wechseln

Standardmäßig wird das Shelled-Entwicklungstool /bin/dashals Interpreter verwendet. Ich habe dies geändert, /bin/bashum eine bessere Kompatibilität mit den meisten Shell-Beispielen im Web und meiner Umgebung zu erreichen.

HINWEIS: Sie können dies ändern, indem Sie zu Fenster -> Einstellungen -> Shell-Skript -> Interpreter wechseln

Setup-Anweisungen

Das Debugger-Paket enthält die folgenden Schritte, um das _DEBUG.shSkript für das Debuggen von Skripten zu verwenden:

  1. Erstellen Sie ein Shell-Skript-Projekt: Datei -> Neu -> Andere -> Shell-Skript -> Shell-Skript-Projekt-Assistent .
  2. Erstellen Sie eine Bash-Skriptdatei: Datei -> Neu -> Datei . Für dieses Beispiel wird es sein script.sh. Die Erweiterung sollte ".sh" sein und ist ein Muss.
  3. Kopieren Sie die Datei _DEBUG.shin den Projektordner.
  4. Fügen Sie den folgenden Text oben in die Datei ein script.sh:

    . _DEBUG.sh
  5. Wenn die Datei in Microsoft Windows erstellt wurde, müssen Sie unbedingt die Befehle Datei -> Zeilentrennzeichen konvertieren nach -> Unix ausführen .

  6. Richten Sie eine Debug-Startkonfiguration ein: Ausführen -> Debug-Konfigurationen -> Bash-Skript ... Hier können Sie zwei Felder festlegen:

    a) "Bash-Skript:" - Pfad im Arbeitsbereich von Eclipse zum zu debuggenden Bash-Skript.
    e) Debugger-Port: 33333

  7. Wechseln Sie in die Debug-Perspektive. Starten Sie die Debugsitzung. Starten Sie script.shvon der Bash-Shell.

Die Bash-Debug-Benutzeroberfläche

Bildbeschreibung hier eingeben

Dieser Bash-Debugger bietet alle Funktionen von Standard-Programmier-Debuggern wie:

  • Haltepunkt umschalten
  • Einzelschritt für Schritt
  • Step-In-, Step-Out-, Step-Over-Funktionen und Unterprogramme
  • Untersuchen von Code oder Variablen zu einem beliebigen Zeitpunkt, während das Skript ausgeführt wird

Die Shelled- IDE (Integrated Development Environment, integrierte Entwicklungsumgebung) (Shell-Skript-Editor) bietet einen zusätzlichen Vorteil: Sie kann beim Schreiben des Skripts den Kontext überprüfen, hervorheben und einrücken. Wenn es nicht richtig eingerückt ist, können Sie möglicherweise sofort viele Fehler dort kennzeichnen / lokalisieren.

Dann gibt es andere IDE-Vorteile wie:

  • TODO-Aufgabenliste
  • Mylyn-Aufgabe
  • Lesezeichenliste
  • Mehrere Fenster bearbeiten
  • Remote Sharing der Umgebung
LD James
quelle
Cooler Tipp. Gut zu wissen, dass Bash so debuggt werden kann.
SLM
8

In den letzten Jahren ist eine wunderbare Ressource erschienen: http://shellcheck.net

Es zeigt Ihnen mehr als die reguläre Bash, so dass Sie mühselige, nicht geschlossene Anführungszeichen, geschweifte Klammern usw. leicht finden können.

Stellen Sie einfach sicher, dass Sie keine vertraulichen Informationen (IPS, Passwörter usw.) über das Internet einfügen. (Ich glaube, Shellcheck kann auch heruntergeladen werden, bin mir aber nicht sicher.)

Olivier Dulac
quelle
6

benutze einfach:

#!/bin/bash -x

das gleiche für shell:

#!/bin/sh -x
Gery
quelle
6

Heutzutage gibt es das VS Code Bash Debug.

https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug

Es hat 'Step in / out / over' und zeigt auch den Wert jeder Variablen.

VS Code Bash Debug Screenshot

Henrique Lemos Ribeiro
quelle
Diese Antwort behandelt die Frage nicht im richtigen Kontext. Annahme der Befehlszeile, da IDE nicht erwähnt wurde
Qodeninja