Ich versuche, die gesamte Ausgabe eines Programms (Steam) nach /dev/null umzuleiten, damit sie nicht im Terminal angezeigt wird.
Folgendes habe ich versucht:
steam & > /dev/null 2>/dev/null
undsteam & > /dev/null 2>&1
Keines von beiden unterdrückt seine Nachrichten in irgendeiner Weise (soweit ich das beurteilen kann).
Nach meinem Verständnis trennt & den Prozess vom Terminal und > leitet die Eingabe/Ausgabe um, wobei der Standardwert/Leerwert > stdout und 2> stderr ist. Gibt es mehr Ausgaben als diese beiden? Warum sehe ich immer noch Ausgaben, wenn ich sie alle umleite?
Antwort1
Versuchen:
steam 2>&1 > /dev/null &
2>&1
leitet stderr zu stdout um und > /dev/null
leitet stdout zu um /dev/null
.
Das &
„to background the process“ wurde falsch platziert. Es muss am Ende der Zeile stehen. Wenn es nach, steam
aber vor platziert wird, wird >
nichts von umgeleitet, obwohl der Prozess ordnungsgemäß in den Hintergrund gestellt wird.steam
Antwort2
Dieses spezielle Problem steam
ist ein Sonderfall, der manchmal spezielles Verständnis und besondere Handhabung erfordert. Die steam
Laufzeit ist ein Wrapper-Skript, das Folgendes enthält:
#!/bin/bash
# default to minimize on close, so we never have a running steam process
# in the background because of a broken Tray Icon on some desktops/WMs
#export STEAM_FRAME_FORCE_CLOSE=${STEAM_FRAME_FORCE_CLOSE:-0}
exec /usr/lib/steam/steam "$@"
Beachten Sie, dass die exec
integrierte Shell verwendet wird und alle Argumente mit übergeben werden $@
.
Die übliche Lösung für die Umleitung der Shell-Ausgabe wäre also ähnlich wie@Adobe & @Garys Antwort, dieser spezielle Falltyp erfordert oft einen etwas differenzierteren Ansatz und ein besseres Verständnis dessen, was hinter den Kulissen vor sich geht. Es gibt einige Feinheiten, warum alle möglichen Ausgabeumleitungsmethoden und die Reihenfolge der Vorgänge steam
manchmal nicht wie erwartet funktionieren.
Die exec
Shell Built-In (erste Nuance)
Der POSIX-Standard definiert ein Verhalten fürder exec
Befehl. Bash stellt dies über dieexec
Shell integriert. Dies kann sich auf die Standard-E/A-Umleitung und, je nach Aufruf, auf den Unterprozessbaum auswirken. Notiz:Obwohl dies im spezifischen Anwendungsfall des OP und den aufgelisteten Befehlen technisch gesehen nicht zutraf, füge ich es hier ein, weil es sich um eine häufige Falle und einen Vorbehalt handelt, dessen man sich bewusst sein sollte.
Aus dem IEEE Std. 1003.1, Ausgabe 2004:
Das Dienstprogramm „exec“ soll Dateideskriptoren gemäß den Angaben in den Umleitungen als Teil des Befehls öffnen, schließen und/oder kopieren.
Wenn exec ohne Befehl oder Argumente angegeben wird und alle Dateideskriptoren mit Nummern größer als 2 mit zugehörigen Umleitungsanweisungen geöffnet werden, ist nicht angegeben, ob diese Dateideskriptoren geöffnet bleiben, wenn die Shell ein anderes Dienstprogramm aufruft. Skripte, die befürchten, dass untergeordnete Shells offene Dateideskriptoren missbrauchen könnten, können diese immer explizit schließen, wie in einem der folgenden Beispiele gezeigt.
Wenn exec mit command angegeben wird, soll es die Shell durch command ersetzen, ohne einen neuen Prozess zu erstellen. Wenn Argumente angegeben werden, sollen diese Argumente für command sein. Die Umleitung betrifft die aktuelle Shell-Ausführungsumgebung.
Die exec /usr/lib/steam/steam "$@"
Zeile im /usr/bin/steam
Wrapper-Skript ersetzt die ausführende /bin/bash
Shell (gemäß der "Shebang-Zeile), ohne einen neuen Unterprozess zu erstellen. Der $@
Argumentspezifizierer wird in Anführungszeichen übergeben, wodurch in den meisten Fällen jegliche Nebeneffekte mit IO-Umleitungsoperatoren vermieden werden sollten. Man sollte sich jedoch darüber im Klaren sein, dass die Übergabe einiger Ausgabe-Umleitungsoperatoren als Argumente (z. B. über fehlerhafte Anführungszeichen "
oder '
über eval
mit Escape-Zeichen \
) die Möglichkeit bieten kann, Shell-Umleitungsoperatoren in das Skript einzufügen, sodass der exec
Aufruf möglicherweise die Standard-IO- und Dateideskriptoren des Befehls beeinflussen würde. Je nachdem, wie Sie oder andere Umleitungsoperatoren an das Wrapper-Skript übergeben 2>&1
, >somefile
werden sie also im Kontext von: ausgewertet "$@"
. Glücklicherweise würden die Anführungszeichen in diesem Fall die meisten Nebeneffekte vermeiden, man muss jedoch darauf achten, welcher Bash-Prozess oder welche Unter-Shell diese Argumente auswertet.
Unix-Ausgabeumleitung: stdin
, stdout
, &stderr
Die meisten UnixREPLShells haben eine ähnliche Methode zur Umleitung derStandard-IO-Streams, stdin
, stdout
, und stderr
. Dies umfasst unter anderem: POSIX sh
, Bash, Z Shell zsh
, Korn Shell ksh
, C Shell csh
, Dash dash
und andere.
Für die Zwecke der Frage des OP konzentrieren wir uns nur auf Bash, da das /usr/bin/steam
Wrapper-Skript mit dem Bash-Befehl "siebang" Linie: #!/bin/bash
.
In Bash werden die ersten drei Dateideskriptoren ( fd
's) immer wie folgt definiert und beginnend bei Null indiziert 0
:
stdin
=fd 0
stdout
=fd 1
stderr
=fd 2
Die Ausgabe eines beliebigen Befehls kann umgeleitet werden mit demAusgabeumleitungsoperatoren in Bash (Bash-Referenzhandbuch: § 3.6 Umleitungen)Eine grundlegende Einführung hierzu finden Sie in diesem Artikel:Bash-Umleitungsspaß mit Deskriptoren. Für eine intuitivere Erklärung mit visuellen Hilfsmitteln,siehe diesen ausgezeichneten Artikel (Sehr empfehlenswert!).
Reihenfolge der Operationen (zweite Nuance):
Es gibt eine subtile Reihenfolge der Operationen zwischen:
- Umleitungsoperatoren(
>
,<
,>>
,<<
,&>
,&>>
,X<&Y
,X>&Y
,X>|Y
,X<&Y-
,X<>Y
, usw...)
... und das:
- Kontrolloperatoren(
&
,;
,\n
/newline
,||
,&&
;;
,;&
,;;&
, ,|
|&
,(
,)
).
Von demBash-Referenzhandbuch § 3.6 Umleitungen:
Weiterleitungen werden in der Reihenfolge ihres Auftretens (von links nach rechts) verarbeitet.
[...SCHNAPP...]
Beachten Sie, dass die Reihenfolge der Umleitungen wichtig ist. Beispielsweise der Befehl
ls > dirlist 2>&1
leitet sowohl die Standardausgabe (Dateideskriptor 1) als auch die Standardfehlerausgabe (Dateideskriptor 2) an die Dateiverzeichnisliste weiter, während der Befehl
ls 2>&1 > dirlist
leitet nur die Standardausgabe an die Datei „Dirlist“ weiter, da der Standardfehler eine Kopie der Standardausgabe erstellt hat, bevor die Standardausgabe an die Datei „Dirlist“ umgeleitet wurde.
Ebenso gibt es eine Operationsreihenfolge für &
und andere Steueroperatoren.
Von demBash-Referenzhandbuch: 2.4 Befehlslisten:
Eine Liste ist eine Folge von einer oder mehreren Pipelines, die durch einen der Operatoren '
;
', '&
', '&&
' oder '||
' getrennt und optional durch einen der Operatoren ';
', '&
' oder ein beendet werdennewline
.Von diesen Listenoperatoren haben '
&&
' und '||
' die gleiche Vorrangstellung, gefolgt von ';
' und '&
', die die gleiche Vorrangstellung haben.Zur Abgrenzung von Befehlen kann eine Folge von einem oder mehreren Zeilenumbrüchen erscheinen
list
, was einem Semikolon entspricht.
Und schließlich insbesondere der Abschnitt über &
:
Wenn ein Befehl durch den Kontrolloperator '
&
' beendet wird, führt die Shell den Befehl asynchron in einer Subshell aus. Dies wird als Ausführen des Befehls in derHintergrund, und diese werden bezeichnet alsasynchronBefehle. Die Shell wartet nicht, bis der Befehl beendet ist, und der Rückgabestatus ist0
(true
). Wenn die Jobsteuerung nicht aktiv ist (sieheJob-Kontrolle), wird die Standardeingabe für asynchrone Befehle, sofern keine explizite Umleitung vorliegt, von umgeleitet/dev/null
.
Warum die Befehle des OP nicht das Erwartete bewirkten
Die ersten beiden ausprobierten Befehle waren:
steam & > /dev/null 2>/dev/null
steam & > /dev/null 2>&1
Der Grund, warum diese nicht die beabsichtigte Umleitung von beiden durchgeführt haben stdout
und stderr
wie erwartet, liegt an den oben genanntenReihenfolge der Operationen / OperatorrangfolgeRegeln, die oben aufgeführt sind. Insbesondere &
wird der Operator zuerst von links nach rechts angezeigt. Er wird auf das erste Wort, den Befehl, angewendet steam
und sendet ihn in den Hintergrund, wo er alsasynchroner Befehl. stdin
ist verbunden mit /dev/null
, während stdout
, und stderr
bleibt verbunden mit der steuerndenPseudoterminal /pty
Dies wird weiter unten erläutert.
Aber zuerst...