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).
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).
Antworten:
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.
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:
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
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 einfach cat
statt grep "^"
? (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
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
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:
... | tee file1 file2
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:
... | tee -a file1 >>file2
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).
sponge
(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
Im Interesse der Vielfalt:
Wenn Ihr System unterstützt /dev/stderr
, dann
(cmd | tee -a /dev/stderr) 2>> file1 >> file2
wird funktionieren. Die Standardausgabe von cmd
wird sowohl an die Standardausgabe als auch an die Standardausgabe der Pipeline gesendet. Der Standardfehler der cmd
Bypässe tee
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.
out+err
undout
bedeuten hier. Dateinamen? Streams umgeleitet werden?