Wie kann ich erreichen
cmd >> file1 2>&1 1>>file2
Das heißt, stdout und stderr sollten zu einer Datei (Datei1) umleiten, und nur stdout (Datei2) sollte zu einer anderen umleiten (beide im Anfügemodus).
Das Problem ist, dass wenn Sie Ihre Ausgabe umleiten, sie für die nächste Umleitung nicht mehr verfügbar ist. Sie können tee
in einer Subshell eine Pipe zu ausführen, um die Ausgabe für die zweite Umleitung beizubehalten:
( cmd | tee -a file2 ) >> file1 2>&1
oder wenn Sie die Ausgabe im Terminal sehen möchten:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Um das Hinzufügen des Stderr des ersten tee
zu vermeiden file1
, sollten Sie das Stderr Ihres Befehls zu einem Dateideskriptor (z. B. 3) umleiten und dies später erneut zu stdout hinzufügen:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(danke @ fra-san)
Mit zsh
:
cmd >& out+err.log > out.log
Im Append-Modus:
cmd >>& out+err.log >> out.log
In zsh
und unter der Voraussetzung der mult_ios
hat Option nicht deaktiviert wurde, wenn ein Dateideskriptor (hier 1) mehrmals zum Schreiben umgeleitet wird, dann die Schale Geräte eines eingebauten, um tee
die Ausgabe zu allen Zielen zu duplizieren.
out+err
undout
bedeuten hier. Dateinamen? Streams umgeleitet werden?cmd >& file1 > file2
Sie könnten: stdout taggen (mit einer UNBUFFERED sed, dh:),
sed -u ...
stderr auch auf stdout gehen lassen (ohne Tag, da es diese Tagging sed nicht durchlaufen hat) und so in der Lage sein, die 2 in der resultierenden Logdatei zu unterscheiden.Folgendes: ist langsam (Es kann ernsthaft optimiert werden, indem zum Beispiel ein Perl-Skript anstelle von while verwendet wird ...; do ...; done, zum Beispiel, das Subshells und Befehle in jeder Zeile erzeugt!), Seltsam (anscheinend brauche ich die 2 {} Stufen, um in der einen stdout umzubenennen und in der anderen stdout die "durchgefallenen" stderr hinzuzufügen) usw. Aber es ist: ein " Proof of Concept ", der versucht zu halten Die Ausgabe ordnet so viel wie möglich von stdout & stderr an:
quelle
ls unknown
), um etwas auf stderr zu drucken?>&2 echo "error"
wäre in Ordnung. (2)tee
kann an mehrere Dateien gleichzeitig angehängt werden. (3) Warum nicht einfachcat
stattgrep "^"
? (4) Ihr Skript schlägt fehl, wenn die Ausgabe von stderr mit beginnt_stdout_
. (5) Warum?ls loop
wird sowohl auf stdout als auch auf stderr ausgegeben, gemischt (alternativ), in einer kontrollierten Reihenfolge, damit wir überprüfen können, ob wir diese stderr / stdout-Reihenfolge trotz der Markierung von stdout beibehalten haben. 2): gnu tail, maybe, but not regulärer Schwanz (ex, aix.). 3): grep "^" zeigt auch beide Dateinamen an. 4): Dies kann durch die Variable geändert werden. 5): Das gewundene Beispiel funktioniert auf alten oses (ex, old aix), wo ich es getestet habe (kein Perl verfügbar).uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)Wenn die Ausgabereihenfolge lauten muss: stdout then stderr ; Es gibt keine Lösung nur mit Umleitung.
Das stderr muss in einer temporalen Datei gespeichert werden
Beschreibung:
Die einzige Möglichkeit, eine Ausgabe (eine fd wie stdout oder stderr) in zwei Dateien umzuleiten, besteht darin, sie zu reproduzieren. Der Befehl
tee
ist das richtige Werkzeug, um den Inhalt eines Dateideskriptors zu reproduzieren. Eine anfängliche Idee, eine Ausgabe für zwei Dateien zu haben, wäre also, Folgendes zu verwenden:Das gibt den Standardwert von tee für beide Dateien (1 & 2) wieder und lässt die Ausgabe von tee ungenutzt. Aber wir müssen anhängen (benutzen
-a
) und brauchen nur eine Kopie. Dies löst beide Probleme:Um
tee
stdout (das zu wiederholende) zu liefern, müssen wir stderr direkt aus dem Befehl heraus konsumieren. Eine Möglichkeit, wenn die Reihenfolge nicht wichtig ist (die Reihenfolge der Ausgabe wird (höchstwahrscheinlich) als generiert beibehalten, je nachdem, was zuerst ausgegeben wird, wird zuerst gespeichert). Entweder:cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
Option 2 funktioniert nur in einigen Shells. Option 3 verwendet eine zusätzliche Unterschale (langsamer), verwendet die Dateinamen jedoch nur einmal.
Aber wenn stdout zuerst sein muss (unabhängig davon, welche Auftragsausgabe generiert wird), müssen wir stderr speichern, um es am Ende an die Datei anzuhängen (erste Lösung veröffentlicht).
quelle
sponge
(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
Im Interesse der Vielfalt:
Wenn Ihr System unterstützt
/dev/stderr
, dannwird funktionieren. Die Standardausgabe von
cmd
wird sowohl an die Standardausgabe als auch an die Standardausgabe der Pipeline gesendet. Der Standardfehler dercmd
Bypässetee
und kommt aus dem Stderr der Pipeline.So
cmd
undcmd
, vermischt.Es ist dann einfach, diese Streams an die richtigen Dateien zu senden.
Wie bei fast jedem Ansatz wie diesem (einschließlich der Antwort von Stéphane )
file1
kann es vorkommen, dass Zeilen aus der Reihenfolge geraten.quelle