Die execShell Built-In (erste Nuance)

Die execShell Built-In (erste Nuance)

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/nullundsteam & > /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>&1leitet stderr zu stdout um und > /dev/nullleitet stdout zu um /dev/null.

Das &„to background the process“ wurde falsch platziert. Es muss am Ende der Zeile stehen. Wenn es nach, steamaber vor platziert wird, wird >nichts von umgeleitet, obwohl der Prozess ordnungsgemäß in den Hintergrund gestellt wird.steam

Antwort2

Dieses spezielle Problem steamist ein Sonderfall, der manchmal spezielles Verständnis und besondere Handhabung erfordert. Die steamLaufzeit 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 execintegrierte 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 steammanchmal nicht wie erwartet funktionieren.

Die execShell Built-In (erste Nuance)

Der POSIX-Standard definiert ein Verhalten fürder execBefehl. Bash stellt dies über dieexecShell 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/steamWrapper-Skript ersetzt die ausführende /bin/bashShell (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 evalmit Escape-Zeichen \) die Möglichkeit bieten kann, Shell-Umleitungsoperatoren in das Skript einzufügen, sodass der execAufruf 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, >somefilewerden 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 dashund andere.

Für die Zwecke der Frage des OP konzentrieren wir uns nur auf Bash, da das /usr/bin/steamWrapper-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:

... und das:

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 werden newline.

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 ist 0( 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 stdoutund stderrwie 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 steamund sendet ihn in den Hintergrund, wo er alsasynchroner Befehl. stdinist verbunden mit /dev/null, während stdout, und stderrbleibt verbunden mit der steuerndenPseudoterminal /ptyDies wird weiter unten erläutert.

Aber zuerst...

Noch mehr execKettenverwirrung!

verwandte Informationen