Ich bin neu bei Linux und versuche zu verstehen, wie Weiterleitungen funktionieren.
Ich habe verschiedene Syntaxen zum Umleiten von stdout
getestet und stderr
in dieselbe Datei, die nicht alle dieselben Ergebnisse liefern.
Wenn ich zum Beispiel versuche, 2 Dateien aufzulisten, die nicht existieren (file1
und file2
) und 2, die dies tun (foo
und fz
):
Syntax #1 (ohne Weiterleitung):
$ ls file1 foo fz file2
Hier ist die Ausgabe, die ich im Terminal bekomme:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo fz
Syntax #2:
Jetzt mit Weiterleitung:
$ ls file1 foo fz file2 > redirect 2>&1
Die redirect
Datei enthält dasselbe wie das Ergebnis für Syntax #1:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Bei beiden obigen Syntaxen scheint die Shell also stderr
auszugeben zuerst, dann stdout
.
Syntax #3:
Wenn ich es jetzt mit einer der folgenden Syntaxen versuche:
$ ls file1 foo fz file2 > redirect 2> redirect
oder
$ ls file1 foo fz file2 2> redirect > redirect
Dann die redirect
Datei wird dies enthalten:
foo
fz
nnot access file1: No such file or directory
ls: cannot access file2: No such file or directory
Hier sieht es wie stdout
aus wird vor stderr
gedruckt , aber dann sehen wir, dass der Anfang von stderr
wird um die gleiche Anzahl von Zeichen „beschnitten“ wie stdout
.
Die stdout
ist 6 Zeichen lang (foo fz
, Carriage Return inklusive), also die ersten 6 Zeichen des stderr
(ls: ca
) wurden von stdout
überschrieben .
Es scheint also tatsächlich stderr
zu sein zuerst gedruckt wurde, und dass stdout
wurde dann über stderr
gedruckt anstatt daran angehängt zu werden.
Allerdings wäre es für mich sinnvoller gewesen, wenn stderr
war vollständig gelöscht und durch stdout
ersetzt , anstatt nur teilweise zu überschreiben.
Syntax #4:
Die einzige Möglichkeit, die ich gefunden habe, um Syntax #3 zu korrigieren, besteht darin, den Append-Operator zu stdout
hinzuzufügen :
$ ls file1 foo fz file2 >> redirect 2> redirect
oder
$ ls file1 foo fz file2 2> redirect >> redirect
Was dasselbe erzeugt wie Syntax #2:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Dieser Artikel hier erklärt, dass Syntax Nr. 3 falsch ist (wahrscheinlich auch Syntax Nr. 4). Aber um der Argumentation willen:Warum ist Syntax #3 falsch? Was genau sagt es aus (oder nicht sagen) die Shell zu tun im Gegensatz zu Syntax #2?
Verwandte:Was ist der Unterschied zwischen $(…) und `…` in Bash?
Gibt es auch einen Grund, warum die Ausgabe immer stderr
anzeigt vor stdout
?
Vielen Dank!
Akzeptierte Antwort:
Es ist genauso, als würden zwei Prozesse ausgeführt, um gleichzeitig in dieselbe Datei zu schreiben … schlechte Idee. Sie landen mit zwei verschiedenen geöffneten Dateihandles und Ihre Daten können verstümmelt werden (wie es in Nr. 3 oben der Fall ist). Die Verwendung von Syntax #2 ist korrekt; es macht eins Datei-Handle und zeigt sowohl stderr als auch stdout auf dieselbe Stelle.
Da stderr immer zuerst gedruckt wird, gibt es dafür keinerlei Regel. Ich vermute mit ls
es liegt daran, dass ls
muss jeden Eintrag im Verzeichnis überprüfen, bevor es tatsächlich feststellen kann, dass eine bestimmte Datei nicht existiert. Anstatt also N Durchläufe über die Verzeichnistabelle zu machen, macht es einen einzigen Durchlauf, prüft auf alle angegebenen Befehlszeilenargumente, meldet die Fehler und druckt die gefundenen Dateien. Andere Befehle können nach stdout auf stderr ausgegeben werden oder sogar zwischen ihnen wechseln.