Ich weiß , wie zu verwenden , tee
die Ausgabe (schreiben STDOUT
) von aaa.sh
zu bbb.out
, während sie noch im Terminal angezeigt wird :
./aaa.sh | tee bbb.out
Wie würde ich jetzt auch STDERR
in eine Datei mit dem Namen schreiben ccc.out
, während sie noch angezeigt wird?
Antworten:
Ich gehe davon aus, dass Sie STDERR und STDOUT weiterhin auf dem Terminal sehen möchten. Sie könnten sich für Josh Kelleys Antwort entscheiden, aber ich finde es
tail
sehr hackisch und ungeschickt , ein Hintergrundbild im Hintergrund zu haben, das Ihre Protokolldatei ausgibt. Beachten Sie, wie Sie ein Exra-FD behalten und anschließend bereinigen müssen, indem Sie es töten, und technisch sollten Sie dies in einem tuntrap '...' EXIT
.Es gibt einen besseren Weg, dies zu tun, und Sie haben es bereits entdeckt :
tee
.Nur, anstatt es nur für Ihr stdout zu verwenden, haben Sie ein T-Stück für stdout und eines für stderr. Wie werden Sie dies erreichen? Prozessersetzung und Dateiumleitung:
Lassen Sie es uns aufteilen und erklären:
>(...)
(Prozessersetzung) erstellt ein FIFO und lässt estee
abhören. Anschließend wird>
(STDOUT) mithilfe von (Dateiumleitung)command
an das FIFO umgeleitet, das Ihr erster Benutzer abhörttee
.Gleiches gilt für die Sekunde:
Wir verwenden die Prozessersetzung erneut, um einen
tee
Prozess zu erstellen, der aus STDIN liest und in diesen speichertstderr.log
.tee
gibt seinen Eingang wieder auf STDOUT aus, aber da sein Eingang unser STDERR ist, möchten wir dentee
STDOUT wieder auf unseren STDERR umleiten . Dann verwenden wir die Dateiumleitung , umcommand
den STDERR zum FIFO-Eingang (tee
STDIN) umzuleiten.Siehe http://mywiki.wooledge.org/BashGuide/InputAndOutput
Die Prozessersetzung ist eines der wirklich schönen Dinge, die Sie als Bonus für die Auswahl
bash
Ihrer Shell im Gegensatz zush
(POSIX oder Bourne) erhalten.In
sh
müssten Sie die Dinge manuell erledigen:quelle
$ echo "HANG" > >(tee stdout.log) 2> >(tee stderr.log >&2)
was funktioniert, wartet aber auf Eingabe. Gibt es einen einfachen Grund, warum dies passiert?/bin/bash 2> err
und/bin/bash -i 2> err
(echo "Test Out";>&2 echo "Test Err") > >(tee stdout.log) 2> >(tee stderr.log >&2)
warum nicht einfach:
Dies leitet einfach
stderr
zu weiterstdout
, sodass das Tee sowohl zum Protokollieren als auch zum Screenen wiedergegeben wird. Vielleicht fehlt mir etwas, weil einige der anderen Lösungen wirklich kompliziert erscheinen.Hinweis: Seit Bash Version 4 können Sie
|&
als Abkürzung verwenden für2>&1 |
:quelle
./aaa.sh |& tee aaa.log
funktioniert es (in bash).set -o pipefail
gefolgt von gefolgt von;
oder&&
wenn ich mich nicht irre.Dies kann nützlich sein, wenn Sie dies über Google finden. Kommentieren Sie einfach das Beispiel aus, das Sie ausprobieren möchten. Natürlich können Sie die Ausgabedateien auch umbenennen.
quelle
exec >
bedeutet, das Ziel eines Dateideskriptors an ein bestimmtes Ziel zu verschieben. Der Standardwert ist 1, daher wirdexec > /dev/null
die Ausgabe von stdout in dieser Sitzung von nun an nach / dev / null verschoben. Die aktuellen Dateideskriptoren für diese Sitzung können durch Ausführen angezeigt werdenls -l /dev/fd/
. Versuch es! Sehen Sie dann, was passiert, wenn Sie ausgeben.exec 2>/tmp/stderr.log.
Außerdemexec 3>&1
bedeutet dies, dass Sie einen neuen Dateideskriptor mit der Nummer 3 erstellen und ihn zum Ziel von Dateideskriptor 1 umleiten. Im Beispiel war das Ziel der Bildschirm, auf dem der Befehl ausgegeben wurde.Um stderr in eine Datei umzuleiten, zeigen Sie stdout auf dem Bildschirm an und speichern Sie stdout in einer Datei:
BEARBEITEN : Um sowohl stderr als auch stdout auf dem Bildschirm anzuzeigen und beide in einer Datei zu speichern, können Sie die E / A-Umleitung von bash verwenden :
quelle
Mit anderen Worten, Sie möchten stdout in einen Filter (
tee bbb.out
) und stderr in einen anderen Filter (tee ccc.out
) leiten . Es gibt keine Standardmethode, um etwas anderes als stdout in einen anderen Befehl zu leiten, aber Sie können dies umgehen, indem Sie Dateideskriptoren jonglieren.Siehe auch Wie grep ich einen Standardfehlerstrom (stderr)? und wann würden Sie einen zusätzlichen Dateideskriptor verwenden?
In bash (und ksh und zsh), aber nicht in anderen POSIX-Shells wie dash, können Sie die Prozessersetzung verwenden :
Beachten Sie, dass dieser Befehl in bash zurückgegeben wird, sobald er
./aaa.sh
beendet ist, auch wenn dietee
Befehle noch ausgeführt werden (ksh und zsh warten auf die Unterprozesse). Dies kann ein Problem sein, wenn Sie so etwas tun./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out); process_logs bbb.out ccc.out
. Verwenden Sie in diesem Fall stattdessen den Dateideskriptor Jonglieren oder ksh / zsh.quelle
sh
Cron-Jobs, bei denen keine Prozessersetzung verfügbar ist.Bei Verwendung von Bash:
Das Guthaben (das nicht von oben beantwortet wird) finden Sie hier: http://www.cygwin.com/ml/cygwin/2003-06/msg00772.html
quelle
In meinem Fall wurde auf einem Skript ein Befehl ausgeführt, während sowohl stdout als auch stderr in eine Datei umgeleitet wurden.
Ich musste es so aktualisieren, dass bei einem Fehler einige Aktionen basierend auf den Fehlermeldungen ausgeführt werden. Ich könnte natürlich das Dup entfernen
2>&1
und das stderr aus dem Skript erfassen, aber dann werden die Fehlermeldungen nicht als Referenz in die Protokolldatei aufgenommen. Während die akzeptierte Antwort von @lhunath dasselbe tun soll, leitet sie umstdout
undstderr
zu verschiedenen Dateien, was nicht das ist, was ich will, aber es hat mir geholfen, die genaue Lösung zu finden, die ich brauche:Mit dem oben genannten hat log eine Kopie von beiden
stdout
undstderr
ich kannstderr
aus meinem Skript erfassen, ohne mir Sorgen machen zu müssenstdout
.quelle
Das Folgende funktioniert für KornShell (ksh), wo die Prozessersetzung nicht verfügbar ist:
Der eigentliche Trick hier ist die Reihenfolge der
2>&1 1>&3
in unserem Fall der Umleitungenstderr
aufstdout
und leitet diestdout
zu Descriptor3
. Zu diesem Zeitpunkt sind diestderr
undstdout
noch nicht kombiniert.Tatsächlich wird das
stderr
(asstdin
) an die Stelle übergeben,tee
an der es sich anmeldet,stderr.log
und es wird auch zu Deskriptor 3 umgeleitet.Und der Deskriptor
3
protokolliert escombined.log
ständig. Dascombined.log
enthält also beidestdout
undstderr
.quelle
Wenn Sie zsh verwenden , können Sie mehrere Umleitungen verwenden, sodass Sie nicht einmal Folgendes benötigen
tee
:Hier leiten Sie einfach jeden Stream zu sich selbst und zur Zieldatei um.
Vollständiges Beispiel
Beachten Sie, dass hierfür die
MULTIOS
Option festgelegt werden muss (dies ist die Standardeinstellung).quelle