Ich habe eine Bash-Datei, die ich brauche, um die gesamte Ausgabe in eine Datei, das Debug-Protokoll sowie an das Terminal umzuleiten. Ich muss sowohl stdout als auch stderr zum Debug umleiten und es für alle Befehle im Skript protokollieren.
Ich möchte 2>&1 | tee -a $DEBUG
für jeden einzelnen Befehl in der Datei. Ich könnte mit | tee -a $DEBUG
.
Ich erinnere mich, dass es eine Möglichkeit gab, dies mit etwas wie exec 2>&1
zu tun .
Derzeit verwende ich etwas wie das Folgende:
#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG
aber es funktioniert nicht. Hat jemand eine Lösung/kann die Ursache erklären?
Akzeptierte Antwort:
Als Lösung, um viele Befehle auf einmal umzuleiten:
#!/bin/bash
{
somecommand
somecommand2
somecommand3
} 2>&1 | tee -a $DEBUGLOG
Warum Ihre ursprüngliche Lösung nicht funktioniert:exec 2>&1 leitet die Standardfehlerausgabe auf die Standardausgabe Ihrer Shell um, die, wenn Sie Ihr Skript von der Konsole aus ausführen, Ihre Konsole sein wird. Die Pipe-Umleitung bei Befehlen leitet nur die Standardausgabe des Befehls um.
Aus der Sicht von somecommand
, seine Standardausgabe geht in eine Pipe, die mit tee
verbunden ist und der Standardfehler geht in dieselbe Datei/Pseudodatei wie der Standardfehler der Shell, die Sie zur Standardausgabe der Shell umleiten, die die Konsole sein wird, wenn Sie Ihr Programm von der Konsole aus ausführen.
Der einzig wahre Weg, es zu erklären, ist zu sehen, was wirklich passiert:
Die ursprüngliche Umgebung Ihrer Shell könnte so aussehen, wenn Sie sie vom Terminal aus ausführen:
stdin -> /dev/pts/42
stdout -> /dev/pts/42
stderr -> /dev/pts/42
Nachdem Sie den Standardfehler in die Standardausgabe umgeleitet haben (exec 2>&1
), du … änderst im Grunde nichts. Wenn Sie jedoch die Standardausgabe des Skripts in eine Datei umleiten, erhalten Sie am Ende eine Umgebung wie diese:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /dev/pts/42
Dann würde das Umleiten des Shell-Standardfehlers in die Standardausgabe so enden:
stdin -> /dev/pts/42
stdout -> /your/file
stderr -> /your/file
Das Ausführen eines Befehls erbt diese Umgebung. Wenn Sie einen Befehl ausführen und ihn an tee weiterleiten, wäre die Umgebung des Befehls :
stdin -> /dev/pts/42
stdout -> pipe:[4242]
stderr -> /your/file
Der Standardfehler Ihres Befehls geht also immer noch in das, was die Shell als Standardfehler verwendet.
Verwandte:${!FOO} und zsh?
Sie können die Umgebung eines Befehls tatsächlich sehen, indem Sie in /proc/[pid]/fd
nachsehen :Verwenden Sie ls -l
um auch den Inhalt des symbolischen Links aufzulisten. Der Datei hier ist die Standardeingabe,
1
ist die Standardausgabe und 2
ist Standardfehler. Wenn der Befehl weitere Dateien öffnet (was bei den meisten Programmen der Fall ist), werden diese ebenfalls angezeigt. Ein Programm kann auch seine Standard-Eingabe/Ausgabe umleiten oder schließen und wiederverwenden ,
1
und 2
.