Connect with us

Wie man

Was sind stdin, stdout und stderr unter Linux?

So vergleichen Sie zwei Textdateien im Linux-Terminal

Fatmawati Achmad Zaenuri / Shutterstock.com

stdin, stdout, und stderr Es werden drei Datenströme erstellt, wenn Sie einen Linux-Befehl starten. Sie können sie verwenden, um festzustellen, ob Ihre Skripte weitergeleitet oder umgeleitet werden. Wir zeigen Ihnen wie.

Streams verbinden zwei Punkte

Sobald Sie sich mit Linux- und Unix-ähnlichen Betriebssystemen vertraut machen, werden Sie auf die Begriffe stoßen stdin, stdout, und stederr. Diese sind drei Standard-Streams Diese werden eingerichtet, wenn ein Linux-Befehl ausgeführt wird. Beim Rechnen kann ein Stream Daten übertragen. Bei diesen Streams handelt es sich bei diesen Daten um Text.

Datenströme haben wie Wasserströme zwei Enden. Sie haben eine Quelle und einen Abfluss. Unabhängig davon, welchen Linux-Befehl Sie verwenden, wird ein Ende jedes Streams bereitgestellt. Das andere Ende wird von der Shell bestimmt, die den Befehl gestartet hat. Dieses Ende wird mit dem Terminalfenster verbunden, mit einer Pipe verbunden oder gemäß der Befehlszeile, die den Befehl gestartet hat, zu einer Datei oder einem anderen Befehl umgeleitet.

Die Linux Standard Streams

Unter Linux stdin ist der Standardeingabestream. Dies akzeptiert Text als Eingabe. Die vom Befehl an die Shell ausgegebene Textübertragung erfolgt über die stdout (Standard Out) Stream. Fehlermeldungen vom Befehl werden über das gesendet stderr (Standardfehler) Stream.

Sie können also sehen, dass es zwei Ausgabestreams gibt: stdout und stderrund ein Eingabestream, stdin. Da Fehlermeldungen und normale Ausgaben jeweils über eine eigene Leitung verfügen, um sie zum Terminalfenster zu übertragen, können sie unabhängig voneinander behandelt werden.

Streams werden wie Dateien behandelt

Streams unter Linux werden – wie fast alles andere – so behandelt, als wären sie Dateien. Sie können Text aus einer Datei lesen und Text in eine Datei schreiben. Beide Aktionen beinhalten einen Datenstrom. Das Konzept, einen Datenstrom als Datei zu verarbeiten, ist also nicht allzu schwierig.

Jeder einem Prozess zugeordneten Datei wird eine eindeutige Nummer zugewiesen, um ihn zu identifizieren. Dies wird als Dateideskriptor bezeichnet. Wann immer eine Aktion für eine Datei ausgeführt werden muss, der Dateideskriptor wird verwendet, um die Datei zu identifizieren.

Diese Werte werden immer für verwendet stdin, stdout, und stderr::

  • : stdin
  • : stdout
  • : stderr

Reagieren auf Pipes und Weiterleitungen

Um jemandem die Einführung in ein Thema zu erleichtern, besteht eine übliche Technik darin, eine vereinfachte Version des Themas zu unterrichten. Zum Beispiel wird uns bei der Grammatik gesagt, dass die Regel „Ich vor E, außer nach C“ lautet. Aber eigentlich da sind weitere Ausnahmen von dieser Regel als es Fälle gibt, die es befolgen.

In ähnlicher Weise, wenn man darüber spricht stdin, stdout, und stderr Es ist zweckmäßig, das akzeptierte Axiom herauszufinden, dass ein Prozess weder weiß noch sich darum kümmert, wo seine drei Standardströme beendet werden. Sollte es einem Prozess wichtig sein, ob seine Ausgabe an das Terminal geht oder in eine Datei umgeleitet wird? Kann es überhaupt erkennen, ob seine Eingabe von der Tastatur kommt oder von einem anderen Prozess in sie geleitet wird?

Tatsächlich weiß ein Prozess Bescheid – oder kann es zumindest herausfinden, falls er sich für eine Überprüfung entscheidet – und kann sein Verhalten entsprechend ändern, wenn der Software-Autor diese Funktionalität hinzufügt.

Wir können diese Verhaltensänderung sehr leicht erkennen. Probieren Sie diese beiden Befehle aus:

ls

ls | cat

Das ls Befehl verhält sich anders, wenn seine Ausgabe (stdout) wird in einen anderen Befehl geleitet. Es ist ls Wenn Sie zu einer einzelnen Spaltenausgabe wechseln, handelt es sich nicht um eine Konvertierung, die von durchgeführt wird cat. Und ls macht dasselbe, wenn seine Ausgabe umgeleitet wird:

ls > capture.txt

cat capture.txt

Stdout und stderr umleiten

Es ist von Vorteil, wenn Fehlermeldungen von einem dedizierten Stream übermittelt werden. Dies bedeutet, dass wir die Ausgabe eines Befehls umleiten können (stdout) in eine Datei und sehen immer noch alle Fehlermeldungen (stderr) im Terminalfenster. Sie können bei Bedarf auf die auftretenden Fehler reagieren. Es verhindert auch, dass die Fehlermeldungen die Datei kontaminieren, die stdout wurde umgeleitet in.

Geben Sie den folgenden Text in einen Editor ein und speichern Sie ihn in einer Datei namens error.sh.

#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

Machen Sie das Skript mit diesem Befehl ausführbar:

chmod +x error.sh

In der ersten Zeile des Skripts wird über das Textfeld Text in das Terminalfenster übertragen stdout Strom. Die zweite Zeile versucht, auf eine nicht vorhandene Datei zuzugreifen. Dies erzeugt eine Fehlermeldung, die über zugestellt wird stderr.

Führen Sie das Skript mit dem folgenden Befehl aus:

./error.sh

Wir können sehen, dass beide Ströme der Ausgabe, stdout und stderrwurden in den Terminalfenstern angezeigt.

Versuchen wir, die Ausgabe in eine Datei umzuleiten:

./error.sh > capture.txt

Die Fehlermeldung, die über übermittelt wird stderr wird weiterhin an das Terminalfenster gesendet. Wir können den Inhalt der Datei überprüfen, um festzustellen, ob die stdout Die Ausgabe ging in die Datei.

cat capture.txt

Die Ausgabe von stdin wurde wie erwartet in die Datei umgeleitet.

Das > Umleitungssymbol funktioniert mit stdout standardmäßig. Sie können einen der numerischen Dateideskriptoren verwenden, um anzugeben, welchen Standardausgabestream Sie umleiten möchten.

Um explizit umzuleiten stdoutVerwenden Sie diese Umleitungsanweisung:

1>

Um explizit umzuleiten stderrVerwenden Sie diese Umleitungsanweisung:

2>

Versuchen wir es noch einmal mit unserem Test, und diesmal verwenden wir 2>::

./error.sh 2> capture.txt

Die Fehlermeldung wird umgeleitet und die stdout echo Nachricht wird an das Terminalfenster gesendet:

Mal sehen, was in der Datei capture.txt enthalten ist.

cat capture.txt

Das stderr Die Nachricht befindet sich erwartungsgemäß in der Datei capture.txt.

Umleiten von stdout und stderr

Sicher, wenn wir auch umleiten können stdout oder stderr zu einer Datei unabhängig voneinander, sollten wir in der Lage sein, beide gleichzeitig in zwei verschiedene Dateien umzuleiten?

Ja wir können. Dieser Befehl leitet stdout zu einer Datei namens capture.txt und stderr zu einer Datei namens error.txt.

./error.sh 1> capture.txt 2> error.txt

Da beide Ausgabeströme – Standardausgabe und Standardfehler – in Dateien umgeleitet werden, ist im Terminalfenster keine sichtbare Ausgabe vorhanden. Wir kehren zur Eingabeaufforderung zurück, als wäre nichts geschehen.

Lassen Sie uns den Inhalt jeder Datei überprüfen:

cat capture.txt
cat error.txt

Umleiten von stdout und stderr in dieselbe Datei

Das ist ordentlich, wir haben jeden der Standardausgabestreams in eine eigene dedizierte Datei verschoben. Die einzige andere Kombination, die wir tun können, ist, beide zu senden stdout und stderr in die gleiche Datei.

Wir können dies mit dem folgenden Befehl erreichen:

./error.sh > capture.txt 2>&1

Lassen Sie uns das aufschlüsseln.

  • : Startet die Skriptdatei error.sh.
  • : Leitet die um stdout Stream in die Datei capture.txt. > ist eine Abkürzung für 1>.
  • : Dies verwendet die Anweisung &> Redirect. Mit dieser Anweisung können Sie der Shell mitteilen, dass ein Stream an dasselbe Ziel wie ein anderer Stream gelangen soll. In diesem Fall sagen wir „Stream 2 umleiten, stderran dasselbe Ziel wie Stream 1, stdoutwird umgeleitet. “

Es gibt keine sichtbare Ausgabe. Das ist ermutigend.

Lassen Sie uns die Datei capture.txt überprüfen und sehen, was darin enthalten ist.

cat capture.txt

Beide stdout und stderr Streams wurden in eine einzelne Zieldatei umgeleitet.

Um die Ausgabe eines Streams umzuleiten und stillschweigend wegzuwerfen, richten Sie die Ausgabe an /dev/null.

Umleitung innerhalb eines Skripts erkennen

Wir haben erläutert, wie ein Befehl erkennen kann, ob einer der Streams umgeleitet wird, und sein Verhalten entsprechend ändern kann. Können wir dies in unseren eigenen Skripten erreichen? Ja wir können. Und es ist eine sehr einfach zu verstehende und anzuwendende Technik.

Geben Sie den folgenden Text in einen Editor ein und speichern Sie ihn als input.sh.

#!/bin/bash

if [ -t 0 ]; then

  echo stdin coming from keyboard
 
else

  echo stdin coming from a pipe or a file
 
fi

Verwenden Sie den folgenden Befehl, um es ausführbar zu machen:

chmod +x input.sh

Der kluge Teil ist der Test in eckigen Klammern. Das -t Die Option (terminal) gibt true (0) zurück, wenn die dem Dateideskriptor zugeordnete Datei wird im Terminalfenster beendet. Wir haben den Dateideskriptor 0 als Argument für den Test verwendet, der darstellt stdin.

Wenn stdin Wird ein Terminalfenster angeschlossen, erweist sich der Test als wahr. Wenn stdin Wird eine Verbindung mit einer Datei oder einer Pipe hergestellt, schlägt der Test fehl.

Wir können jede bequeme Textdatei verwenden, um Eingaben in das Skript zu generieren. Hier verwenden wir eine namens dummy.txt.

./input.sh < dummy.txt

Die Ausgabe zeigt, dass das Skript erkennt, dass die Eingabe nicht von einer Tastatur, sondern von einer Datei stammt. Wenn Sie möchten, können Sie das Verhalten Ihres Skripts entsprechend variieren.

Das war mit einer Dateiumleitung, versuchen wir es mit einer Pipe.

cat dummy.txt | ./input.sh

Das Skript erkennt, dass seine Eingabe in das Skript geleitet wird. Genauer gesagt erkennt es noch einmal, dass die stdin Der Stream ist nicht mit einem Terminalfenster verbunden.

Lassen Sie uns das Skript weder mit Pipes noch mit Weiterleitungen ausführen.

./input.sh

Das stdin Der Stream ist mit dem Terminalfenster verbunden, und das Skript meldet dies entsprechend.

Um dasselbe mit dem Ausgabestream zu überprüfen, benötigen wir ein neues Skript. Geben Sie Folgendes in einen Editor ein und speichern Sie es als output.sh.

#!/bin/bash

if [ -t 1 ]; then

echo stdout is going to the terminal window
 
else

echo stdout is being redirected or piped
 
fi

Verwenden Sie den folgenden Befehl, um es ausführbar zu machen:

chmod +x input.sh

Die einzige wesentliche Änderung an diesem Skript ist der Test in eckigen Klammern. Wir verwenden die Ziffer 1, um den Dateideskriptor für darzustellen stdout.

Probieren wir es aus. Wir werden die Ausgabe durchleiten cat.

./output | cat

Das Skript erkennt, dass seine Ausgabe nicht direkt in ein Terminalfenster geleitet wird.

Wir können das Skript auch testen, indem wir die Ausgabe in eine Datei umleiten.

./output.sh > capture.txt

Es erfolgt keine Ausgabe an das Terminalfenster. Wir kehren stillschweigend zur Eingabeaufforderung zurück. Wie wir es erwarten würden.

Wir können in die Datei capture.txt schauen, um zu sehen, was erfasst wurde. Verwenden Sie dazu den folgenden Befehl.

cat capture.sh

Auch hier stellt der einfache Test in unserem Skript fest, dass die stdout Der Stream wird nicht direkt an ein Terminalfenster gesendet.

Wenn wir das Skript ohne Pipes oder Umleitungen ausführen, sollte es dies erkennen stdout wird direkt an das Terminalfenster geliefert.

./output.sh

Und genau das sehen wir.

Ströme des Bewusstseins

Wenn Sie wissen, wie Sie feststellen können, ob Ihre Skripte mit dem Terminalfenster oder einer Pipe verbunden sind oder umgeleitet werden, können Sie deren Verhalten entsprechend anpassen.

Die Protokollierungs- und Diagnoseausgabe kann mehr oder weniger detailliert sein, je nachdem, ob sie auf dem Bildschirm oder in einer Datei angezeigt wird. Fehlermeldungen können in einer anderen Datei als der normalen Programmausgabe protokolliert werden.

Wie gewöhnlich bringt mehr Wissen mehr Optionen.

Continue Reading
Click to comment

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Tendencia