Stimmt es, dass es vier Arten vonStream-Ausgabewir können auf eine Datei in Linux verweisen, wenn wir nicht möchten, dass sie nach der Ausführung ihres Befehls in der CLI angezeigt wird?
Mögliche Verweise auf eine Datei:
- Alle Stream-Ausgaben
- Nur stderr
- Nur stdout (einschließlich des Endergebnisses von stdout).
- stdout und stderr (ohne das Endergebnis von stdout).
Anmerkungen:
Ein Beispiel für Nummer 4 könnte sein find / -type f -name php.ini 2>/dev/null
. So wie ich es verstehe, erhalten wir mit diesem Befehl weder stderr noch stdout (außer demEndergebnis von stdoutDies ist in diesem Fall die gesuchte Datei, sofern sie gefunden wurde).
Antwort1
Mit jedem Prozess auf einem Unix-System sind zwei Ausgabeströme verbunden:Standardausgabe(stdout, Dateideskriptor 1) undStandart Fehler(stderr, Dateideskriptor 2). Diese können unabhängig voneinander umgeleitet werden.Standardeingabeverwendet Dateideskriptor 0.
- Um die Standardausgabe in die Datei umzuleiten
file
, verwenden Sie>file
oder die explizitere Option1>file
. Ersetzen Siefile
durch ,/dev/null
um die Daten zu verwerfen. - Um die Standardfehlermeldung zur Datei umzuleiten
file
, verwenden Sie2>file
. - Um die Standardfehlermeldung dorthin umzuleiten, wo die Standardausgabe hingeht, verwenden Sie
2>&1
. - Um die Standardausgabe dorthin umzuleiten, wo die Standardfehlerausgabe hingeht, verwenden Sie
1>&2
.
Es gibt kein Konzept des „Endergebnisses“ eines Streams oder Prozesses. Ich nehme an, dass alles, was an die Standardausgabe gesendet wird, als „Ergebnis“ eines Prozesses angesehen werden kann, es sei denn, es gibt auch Daten in eine Datei aus, die es selbst öffnet, oder es hat andere Nebeneffekte (wie das Aufheben der Verknüpfung einer Datei mit einem Verzeichnis im Fall von rm
oder die Handhabung einer Reihe von Netzwerkverbindungen im Fall von sshd
). Ein Prozess gibt auch einen Beendigungsstatus zurück (Null für „Erfolg“ und ungleich Null für „Fehler“), der als „Ergebnis“ dieses Prozesses angesehen werden könnte, aber dies hat nicht unbedingt etwas mit den Ausgabestreams des Prozesses zu tun.
Streams können auch umgeleitet werden inAnfügemodus, was bedeutet, dass bei einer Umleitung zu einer Datei diese Datei zunächst nicht abgeschnitten wird und alle Daten im Stream an das Ende der Datei angehängt werden. Dies geschieht durch die Verwendung von >>file
anstelle von >file
.
In der Anmerkung zur Frage wird der Befehl
find / -type f -name php.ini 2>/dev/null
gegeben ist. Dies leitet um (verwirft)nurStandardfehler. Der Standardausgabestrom wird überhaupt nicht umgeleitet und ist daher in seiner Gesamtheit in der Konsole oder im Terminal sichtbar. Wenn es sich um einen Zwischenteil einer Pipeline handeln würde, würde der Standardausgabestrom in die Standardeingabe des nächsten Befehls in der Pipeline eingespeist.
Abschließend möchte ich sagen, dass eszwei(nicht vier) Ausgabeströme. Diese können unabhängig voneinander auf verschiedene Weise umgeleitet werden, was auch das Verwerfen ihres Inhalts einschließt.
Antwort2
JedenVerfahrenkann laut Konvention drei Standarddateideskriptoren verwenden. Diese Dateideskriptoren sind als Streams verfügbar: stdin
, stdout
, und stderr
.
Wenn Sie einen Prozess von einer Shell (CLI) aus starten, wird standardmäßig der erste mit dem Eingang Ihres Terminals (oder Terminalemulators wie xterm) und die anderen beiden mit dem Ausgang Ihres Terminals verbunden.
Sie können die Shell anweisen, sie woandershin umzuleiten, beispielsweise nach /dev/null
(wo sie einfach verschluckt werden). Und Sie können das unabhängig für stdout
und tun stderr
. Für diesen Fall gibt es also tatsächlich vier Möglichkeiten:
command
command > /dev/null
command 2> /dev/null
command > /dev/null 2> /dev/null
Sie können jedoch auch einen oder beide Werte woanders hin umleiten:
command > /tmp/myout 2> /tmp/myerr
In diesem Fall erhalten Sie auch keine Ausgabe in Ihrem Terminal, können diese aber später in den Dateien /tmp/myout
und lesen /tmp/myerr
.
Antwort3
Die Situation ist einfacher und komplizierter, als Ihre Frage vermuten lässt. Um es zusammenzufassen:Kusalanandasagt inseine Antwortgibt es zwei standardmäßige (konventionelle) I/O-Streams (Dateideskriptoren), die konventionell konfiguriert und für die Ausgabe verwendet werden: stdout (Dateideskriptor 1) und stderr (Dateideskriptor 2). Unsere kanonische Frage, Was sind die Steuer- und Umleitungsoperatoren der Shell?, erläutert, wie man sie umleitet. Naiv betrachtet können wir fünf verschiedene Kombinationen aufzählen:
╔══════════════════════════════╦═════════════════════════════════════════════╗
║ ║ stderr ║
║ ╟─────────────────────┬───────────────────────╢
║ ║ default │ ║
║ ║ (same as the shell) │ redirected ║
╠════════╤═════════════════════╬═════════════════════╦═══════════════════════╣
║ │ default ║ ║ ║
║ │ (same as the shell) ║ 1 ║ 2 ║
║ ├─────────────────────╠═════════════════════╬═══════════════════════╣
║ stdout │ ║ ║ 4. redirected ║
║ │ ║ ║ to the same file ║
║ │ redirected ║ 3 ╟───────────────────────╢
║ │ ║ ║ 5. redirected ║
║ │ ║ ║ to different files ║
╚════════╧═════════════════════╩═════════════════════╩═══════════════════════╝
aber wenn Sie es /dev/null
als etwas anderes als eine Datei betrachten, den Anfügemodus als Sonderfall, den Lese-/Schreibmodus als etwas anderes als den Nur-Schreibmodus und Pipes als etwas anderes als Dateien, dann steigt die Anzahl der Kombinationen exponentiell. Wie jedoch wiederholt festgestellt wurde, ist „das Endergebnis von stdout“ kein Standardausdruck für Unix/Linux/Bash.
Nur zwei?
Die anderen Antworten (vielleicht klugerweise) beschränkten sich auf stdout und stderr (Dateideskriptoren 1 und 2). Ich bin (rücksichtslos?) der Meinung, dass eine vollständige Antwort auf diese Frage die Tatsache berücksichtigen sollte, dass andere Dateideskriptoren verfügbar sind – bis zu Hunderten, Tausenden oder sogarüber eine Million. Wenn Sie beispielsweise einen Befehl wie ausführen , öffnet sich diff file1 file2
das Programm und , und der Kernel weist wahrscheinlich die Dateideskriptoren 3 und 4 zu. Der Unterschied besteht darin, dass nur die Dateideskriptoren 0, 1 und 2 vordefiniert sind. Die Umleitung von Dateideskriptoren höher als 2 wird an den folgenden Stellen erläutert:diff
file1
file2
- Bash-Referenzhandbuch: Abschnitt 3.6 Umleitungen
- Erweitertes Bash-Scripting-Handbuch: Kapitel 20. I/O-Umleitung
- Unterschied zwischen 2>&-, 2>/dev/null, |&, &>/dev/null und >/dev/null 2>&1(U&L-Frage)
- Können wir mehr Dateideskriptoren haben als die üblichen stdin/stdout/stderr (0, 1, 2)?(Stack Overflow-Frage)
Sehen Sie sich beispielsweise dieses Beispiel eines High-File-Deskriptors an:
$ Katze Hund.c #include <stdio.h> #include <string.h> hauptsächlich() { int i, Länge; char msg[] = "Hallo, Hund.\n"; len = strlen(msg); i = schreibe(17, Nachricht, Länge); wenn (i == Länge) printf("Erfolgreich! i = %d = len\n", i); sonst wenn (i == -1) { printf("Fehler! i = %d (Länge = %d)\n", i, Länge); perror(""); } anders printf("Unerwartetes Ergebnis: i = %d, len = %d\n", i, len); } $ machen Eckzahn cc Hund.c -o Hund $ ./Hund Fehler! i = -1 (Länge = 12) Ungültiger Dateideskriptor $ ./Hund 17> Tier Erfolg! i = 12 = len $ ls -l insgesamt 70 -rw-r--r-- 1meinBenutzername meinGruppenname 12 Apr 12 13:36 Tier -rwxr-xr-x 1meinBenutzername meinGruppenname67067 Apr 12 13:36 Hund -rw-r--r-- 1meinBenutzername meinGruppenname 358 Apr 12 13:36 canine.c $ Katze Tier Hallo Hund.
Warnung: Ich bin nicht sicher, ob das oben Genannte für alle Versionen aller Shells funktioniert.
Standardprogramme schreiben nicht in Dateideskriptoren, die höher als 2 sind (es sei denn, sie haben diesen Dateideskriptor vom Kernel erhalten, indem sie eine Datei geöffnet, eine Netzwerkverbindung hergestellt oder etwas Ähnliches gemacht haben). Wenn Sie jedoch ein (nicht standardmäßiges) Programm haben, das dies tut, können Sie diese Dateideskriptoren umleiten.
Und wenn Sie lediglich 100 Dateideskriptoren haben und nur berücksichtigen, ob jeder einzelne umgeleitet wird oder nicht, haben Sie über eine Nonillion (1.000.000.000.000.000.000.000.000.000.000) mögliche Kombinationen.