Senden Sie die Ausgabe von bash -x an die Protokolldatei, ohne die Standardausgabe zu unterbrechen

12

Gibt es eine Möglichkeit, die angezeigten Informationen durch Ausführen eines Bash-Skripts mit der Option -x in eine Datei zu senden, ohne die Standardausgabe zu ändern, die von einem Benutzer angezeigt wird, der das Skript ausführt?

Dies ist eine Debugging-Funktion, die ich in ein Bash-Skript implementieren möchte, das wir häufig verwenden und das sich ändert.

Sehr geschätzt.

Entschuldigung Doktor von Pink
quelle

Antworten:

20

Die Ausgabe von -x geht an stderr, nicht an stdout. Aber selbst das kann ein Problem sein - viele Skripte werden funktionale Abhängigkeiten vom Inhalt von stderr haben und es ist in manchen Fällen etwas chaotisch, den Debug- und den stderr-Stream miteinander zu mischen.

Bash-Versionen> 4.1 bieten eine andere Lösung: Mit der Umgebungsvariablen BASH_XTRACEFD können Sie einen Dateideskriptor angeben, an den der Debug-Stream gesendet wird. Dies kann eine Datei, eine Pipe oder eine andere Unix-Qualität sein, die Sie mögen.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Mit ein bisschen mehr Fummelei können Sie andere Dinge tun - zum Beispiel ein T-Stück auf den stdout- und / oder stdin-Streams machen und diese mit der Debug-Ausgabe verschachteln, damit Ihr Protokoll vollständiger wird. Weitere Informationen hierzu finden Sie unter /programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

Der große Vorteil dieses Ansatzes gegenüber Alternativen besteht darin, dass Sie keine Änderungen am Verhalten Ihres Skripts riskieren, indem Sie die Debug-Ausgabe in stdout oder stderr einfügen.

Stabledog
quelle
Lesen Sie auch hier, wie Sie einen nicht verwendeten Dateideskriptor für die Datei finden.
jarno
Muss der Dateideskriptor (dh die Zeile exec 19>&-) geschlossen werden? Nach meiner Erfahrung wird es automatisch geschlossen, wenn das Skript beendet ist.
jarno
1
Der oben gezeigte Code setzt nicht voraus, dass Sie ein Skript ausführen oder wie lange das Skript möglicherweise ausgeführt wird usw. Wenn Sie nur das tun, was dieses Snippet tut, und dies in ein Skript einfügen, wird das Datei-Handle verwendet geschlossen werden, nur weil die ganze Shell am Ende des Skripts verschwindet. In diesem Anwendungsfall muss der Griff also nicht unbedingt geschlossen werden. Im Allgemeinen empfiehlt es sich jedoch, beim Codieren anhand einer Ressource zu schließen, was Sie geöffnet haben, da Ihr Code dann in einem größeren Kontext verwendet werden kann, in dem es eher auf die Verwaltung ankommt.
Stabledog
Warum exportieren Sie BASH_XTRACEFD? Warum nicht einfach Wert dafür setzen?
jarno
Eine alternative Möglichkeit, den Dateideskriptor zu schließen, besteht darin, für BASH_XTRACEFD einen neuen Wert (z. B. null) festzulegen oder diesen zu deaktivieren.
jarno
4

set -xsendet nichts an die Standardausgabe, daher gibt es dort kein Problem. Was sie nicht tun , ist Schreiben auf Standardfehler, die standardmäßig auf die Konsole geht.

Was Sie tun möchten, ist stdout in eine andere Datei umzuleiten:

/bin/sh -x /my/script/file 2>/my/log/file
womble
quelle
1

Sehen man tee.

Sie führen es wie tee commandname filenamefolgt aus und es werden die Befehle angezeigt, die ausgegeben werden, stdoutund es wird auch in geschrieben filename.

Sven
quelle