BEARBEITEN
Bitte sehen Sie sich nicht nur die akzeptierte Antwort an, sondern auch die anderen.
Frage
Warum funktioniert die Umleitung von STDOUT und STDERR zur gleichen Datei nicht, obwohl es so aussieht wie 1>[DATEINAME] 2>&1?
Hier ist ein Beispiel:
perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>a.txt
cat a.txt
# outputs '1' only.
Nun, warum? Ich dachte, das funktioniert, weil ... STDOUT zu a.txt umgeleitet wird, ebenso wie STDERR. Was ist mit STDERR passiert?
Antwort1
Beide Umleitungen kürzen die Datei, so dass die zweite (in chronologischer Reihenfolge der Ausführung) die erste überschreibt. Versuchen Sie
rm a.txt ; touch a.txt ; perl -e 'print "1\n" ; warn "2\n";' 1>>a.txt 2>>a.txt
Oder verwenden Sie einfach den gleichen Dateideskriptor
perl -e 'print "1\n" ; warn "2\n";' 1>a.txt 2>&1
Antwort2
Mit 1>a.txt 2>&1
ist Dateideskriptor Nr. 1dupliziertzu Nr. 2. Sie verweisen beide auf dieselbe „geöffnete Datei“ und haben beide die gleiche aktuelle Position und den gleichen Schreib-/Lesemodus. (Tatsächlich gibt es überhaupt keinen Unterschied zwischen der Verwendung von 2>&1 und 2<&1.)
Mit 1>a.txt 2>a.txt
werden beide Dateideskriptorenunabhängig voneinander geöffnetund haben separate Cursorpositionen. (Die Datei wird außerdem zweimal abgeschnitten.) Wenn Sie „Hallo“ in fd #1 schreiben, wird seine Position auf Byte 5 vorgerückt, aber fd #2 bleibt bei Byte 0. Beim Drucken in fd #2 werden die Daten einfach beginnend bei 0 überschrieben.
Dies lässt sich leicht erkennen, wenn der zweite Schreibvorgang kürzer ist:
$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>a.txt
$ cat a.txt
123defg
Beachten Sie, dass Perl über interne Pufferung verfügt. In diesem Beispiel ist daher ein explizites „flush()“ erforderlich, um sicherzustellen, dass die Daten von fd #1 vor den Daten von fd #2 geschrieben werden. Andernfalls würden die Streams beim Beenden in unvorhersehbarer Reihenfolge geleert.
Zum Vergleich: Wenn die Dateideskriptoren gemeinsam genutzt werden, folgen die Schreibvorgänge einfach aufeinander:
$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>&1
$ cat a.txt
abcdefg
123