Wie wird das Bash-Skript Zeile für Zeile ausgeführt?

92

Wenn ich eintrete Option bash -x eingebe, wird die gesamte Zeile angezeigt . Das Skript wird jedoch normal ausgeführt.

Wie kann ich Zeile für Zeile ausführen? Dann kann ich sehen, ob es das Richtige tut, oder ich brich den Fehler ab und behebe ihn. Der gleiche Effekt wird readin jede Zeile eingefügt.

Rodrigo
quelle
1
Vielleicht allgemeiner siehe auch stackoverflow.com/questions/951336/how-to-debug-a-bash-script/…
Tripleee

Antworten:

125

Sie müssen nicht in jede Zeile einen Lesevorgang einfügen, sondern fügen einfach eine Falle wie die folgende in Ihr Bash-Skript ein. Sie hat den gewünschten Effekt, z.

#!/usr/bin/env bash
set -x
trap read debug

< YOUR CODE HERE >

Funktioniert, habe es gerade mit bash v4.2.8 und v3.2.25 getestet.


VERBESSERTE VERSION

Wenn Ihr Skript Inhalte aus Dateien liest, funktioniert die oben aufgeführte nicht. Eine Problemumgehung könnte wie folgt aussehen.

#!/usr/bin/env bash
echo "Press CTRL+C to proceed."
trap "pkill -f 'sleep 1h'" INT
trap "set +x ; sleep 1h ; set -x" DEBUG

< YOUR CODE HERE >

Um das Skript zu stoppen, müssten Sie es in diesem Fall von einer anderen Shell aus beenden .


ALTERNATIVE1

Wenn Sie nur einige Sekunden warten möchten, bevor Sie mit dem nächsten Befehl in Ihrem Skript fortfahren, kann das folgende Beispiel für Sie funktionieren.

#!/usr/bin/env bash
trap "set +x; sleep 5; set -x" DEBUG

< YOUR CODE HERE >

Ich füge set + x und set -x zum Trap-Befehl hinzu, um die Ausgabe besser lesbar zu machen.

Bio-Mashup
quelle
1
Wie gelangen Sie dann zur nächsten Zeile (führen Sie den nächsten Befehl aus)?
David Doria
2
Bei jedem Befehl wird ein Lesevorgang abgefangen. Sie müssen nur die Eingabetaste drücken, um zum nächsten Befehl zu gelangen
Organic-Mashup
1
Wenn Sie Befehlszeilen wie diese haben "während der Lesezeile; geben Sie $ line zurück; done <somefile", funktioniert diese Methode nicht, weil "trap read DEBUG" die Lesezeile von somefile liest
mug896
3
Wie lässt du es aufhören? Nachdem ich das Skript bis zum Ende durchlaufen habe, verhält sich die Shell so, als würde das Skript noch ausgeführt.
Slashdottir
1
Wechseln Sie zu trap 'read -u1' debug, um das Problem der Dateiumleitung zu überschreiben.
user3132194
23

Vielleicht ist der BASH Debugger etwas für Sie.


quelle
3
Dies ist wirklich die beste Lösung. Es ermöglicht das Anzeigen der Linie, bevor sie ausgeführt wird (und vieles mehr). Auf den meisten Systemen kann es mit installiert werden apt-get install bashdb. Dann müssen Sie nur noch ausführen bashdb your_command.sh, tippen stepund danach den Wagenrücklauf drücken.
Studgeek
1
@studgeek es ist nicht verfügbar unter Redhat / CentOS usw., daher würde ich das nicht "die meisten Systeme" nennen.
Sajuuk
@Sajuuk, es ist möglicherweise nicht verpackt , aber es ist absolut verfügbar .
Charles Duffy
macOS:brew install bashdb
Boweeb
@CharlesDuffy: Es ist auch nicht in den Standard-Ubuntu-Repos.
Dan Dascalescu
2

Wenn es sich bei Ihrem Bash-Skript wirklich um eine Reihe von Einzelbefehlen handelt, die Sie einzeln ausführen möchten, können Sie Folgendes tun: Jeder Befehl wird einzeln ausgeführt, wenn Sie eine Variable inkrementieren LN , die der Zeilennummer entspricht, die Sie ausführen möchten . Auf diese Weise können Sie den letzten Befehl ganz einfach erneut ausführen und dann die Variable inkrementieren, um zum nächsten Befehl zu gelangen.

Angenommen, Ihre Befehle befinden sich in einer Datei "it.sh", führen Sie die folgenden Schritte nacheinander aus.

$ cat it.sh
echo "hi there"
date
ls -la /etc/passwd

$ $(LN=1 && cat it.sh | head -n$LN | tail -n1)
"hi there"

$ $(LN=2 && cat it.sh | head -n$LN | tail -n1)
Wed Feb 28 10:58:52 AST 2018

$ $(LN=3 && cat it.sh | head -n$LN | tail -n1)
-rw-r--r-- 1 root wheel 6774 Oct 2 21:29 /etc/passwd
Brad Parks
quelle
1

xargs: kann Zeilen filtern

cat .bashrc | xargs -0 -l -d \\n bash
  • -0 Als Roheingabe behandeln (kein Entkommen)
  • -l Trenne jede Zeile (nicht standardmäßig für Aufführungen)
  • -d \\ n Das Zeilentrennzeichen
Tinmarino
quelle