VMware ESXi and vSphere Cluster Management

Datenströme in Linux: Standardeingabe, Standardausgabe und Standardfehlerausgabe

Verstehe stdin, stdout und stderr in Linux und lerne, Datenströme mit Umleitungen und Pipes sicher zu verarbeiten.

Linux-Programme verarbeiten Daten über Ein- und Ausgabekanäle. Im interaktiven Terminal kommt die Eingabe typischerweise von der Tastatur. Reguläre Ausgaben und Fehlermeldungen erscheinen im Terminalfenster. Die Shell kann diese Verbindungen jedoch auf Dateien, Geräte oder andere Programme umleiten.

Diese Kanäle heißen Datenströme. Ein Datenstrom ist ein fortlaufender Datenkanal, über den ein Prozess Eingaben empfängt oder Ausgaben sendet. Die drei wichtigsten Standarddatenströme sind stdin, stdout und stderr.

Die drei Standarddatenströme

Ein Dateideskriptor ist eine Nummer, mit der ein Prozess auf einen geöffneten Ein- oder Ausgabekanal verweist. Linux reserviert für die drei Standarddatenströme die Dateideskriptoren 0, 1 und 2.

StromAbkürzungDateideskriptorStandardquelle oder StandardzielTypischer Inhalt
Standardeingabestdin0TastaturEingabedaten
Standardausgabestdout1TerminalReguläre Ergebnisse und Statusausgaben
Standardfehlerausgabestderr2TerminalFehlermeldungen und Diagnosen

Standardeingabe: stdin

stdin ist der voreingestellte Eingabestrom eines Programms. Bei einem interaktiven Befehl ist die Tastatur normalerweise die Quelle. Ein Programm kann aber ebenso Daten aus einer Datei oder von einem anderen Programm über stdin lesen.

Standardausgabe: stdout

stdout ist der voreingestellte Strom für reguläre Ergebnisse. Wenn ein Befehl eine Dateiliste, berechnete Werte oder andere normale Ergebnisse ausgibt, verwendet er dafür üblicherweise stdout.

Standardfehlerausgabe: stderr

stderr ist ein eigener Ausgabestrom für Fehlermeldungen und Diagnoseausgaben. stdout und stderr erscheinen ohne Umleitung meist an derselben Stelle, nämlich im Terminal. Technisch sind sie trotzdem getrennt. Diese Trennung ermöglicht es, Ergebnisse und Fehler unabhängig voneinander zu speichern oder weiterzuverarbeiten.

Standardverhalten im Terminal

Ohne Umleitung verbindet die Shell die Standardströme eines interaktiven Programms normalerweise mit dem aktiven Terminal:

  • stdin liest von der Tastatur.
  • stdout schreibt reguläre Ausgaben in das Terminal.
  • stderr schreibt Fehlermeldungen ebenfalls in das Terminal.

Ein Befehl kann daher beispielsweise eine normale Ausgabe und gleichzeitig eine Fehlermeldung anzeigen. Für die Shell sind das zwei verschiedene Ströme, auch wenn beide im selben Terminalfenster sichtbar sind.

Ausgabeumleitung mit > und >>

Standardausgabe in eine Datei schreiben

Der Operator > leitet stdout in eine Datei um. Existiert die Datei bereits, wird ihr bisheriger Inhalt ersetzt. Existiert sie noch nicht, legt die Shell sie normalerweise an.

ls > dateiliste.txt

Die Dateiliste wird dadurch in dateiliste.txt gespeichert und nicht im Terminal angezeigt.

Ausgabe an eine Datei anhängen

Mit >> wird stdout am Ende einer Datei angefügt. Das ist für fortlaufende Protokolle oder Ergebnisse mehrerer Ausführungen geeignet.

date >> protokoll.txt

Standardfehlerausgabe umleiten

Die Nummer des Dateideskriptors steht vor dem Umleitungsoperator. Mit 2> wird ausschließlich stderr in eine Datei geschrieben:

ls /nicht-vorhanden 2> fehler.txt

Zum Anhängen von Fehlermeldungen dient 2>>:

ls /nicht-vorhanden 2>> fehler.log

stdout bleibt dabei unverändert. Reguläre Ausgaben erscheinen weiterhin im Terminal, sofern sie nicht ebenfalls umgeleitet werden.

Eingabeumleitung mit <

Der Operator < verwendet den Inhalt einer Datei als stdin eines Befehls.

sort < namen.txt

sort liest in diesem Beispiel die Namen über stdin und gibt die sortierte Ausgabe nach stdout aus. Der Befehl erhält keinen Dateinamen als Argument.

Das unterscheidet sich von:

sort namen.txt

Hier bekommt sort den Dateinamen als Befehlsargument und öffnet die Datei selbst. Beide Varianten können zu einem ähnlichen Ergebnis führen, aber die Daten kommen auf unterschiedlichen Wegen zum Programm: einmal über stdin, einmal über ein Argument.

Befehle mit Pipes verbinden

Eine Pipe verbindet die Standardausgabe eines Befehls direkt mit der Standardeingabe des nächsten Befehls. Das Symbol dafür ist |. Die Shell startet damit eine Verarbeitungskette, in der ein Programm die Daten für das nächste liefert.

cat namen.txt | sort

cat schreibt den Dateiinhalt nach stdout. Die Pipe macht diesen Strom zu stdin von sort. Das Ergebnis von sort wird anschließend wieder über stdout ausgegeben.

Für die Verarbeitung von Dateinamen mit einem Muster ist beispielsweise folgende Kette möglich:

printf '%s\n' *.txt | sort

Das Muster *.txt wird von der Shell auf passende Dateinamen erweitert. printf gibt diese Namen zeilenweise aus, und sort ordnet sie.

Kombinierte Umleitungen

stdout und stderr getrennt speichern

Mit zwei Umleitungen lassen sich reguläre Ausgaben und Fehlermeldungen in unterschiedliche Dateien schreiben:

ls /vorhanden /nicht-vorhanden > ergebnis.txt 2> fehler.txt

Die erfolgreiche Ausgabe landet in ergebnis.txt. Die Fehlermeldung für den nicht vorhandenen Pfad landet in fehler.txt.

Allgemein gilt:

befehl > ausgabe.txt 2> fehler.txt

stdout und stderr gemeinsam speichern

Mit 2>&1 wird stderr an dasselbe Ziel wie stdout gebunden. Die übliche portable Schreibweise lautet:

befehl > protokoll.txt 2>&1

Zuerst wird stdout auf protokoll.txt umgeleitet. Danach wird stderr auf das aktuelle Ziel von stdout gesetzt. Beide Ströme landen deshalb in derselben Datei.

Viele Shells unterstützen zusätzlich die Kurzform &>:

befehl &> protokoll.txt

2>&1 ist jedoch die besser übertragbare Schreibweise zwischen verschiedenen Shell-Umgebungen.

Warum die Reihenfolge wichtig ist

Umleitungen werden von der Shell in der angegebenen Reihenfolge verarbeitet. Diese beiden Befehle sind daher nicht gleich:

befehl > datei.txt 2>&1
befehl 2>&1 > datei.txt

Im ersten Fall zeigen stdout und stderr auf datei.txt. Im zweiten Fall wird stderr zunächst auf das damalige stdout-Ziel, meist das Terminal, gesetzt. Die spätere Umleitung von stdout ändert stderr nicht mehr. Dadurch kann stderr weiterhin im Terminal erscheinen.

Operatoren im Überblick

SyntaxBetroffener StromWirkungHinweis
<stdinLiest eine Datei als StandardeingabeDie Datei wird Quelle des Programms
>stdoutSchreibt in eine DateiVorhandener Inhalt wird ersetzt
>>stdoutHängt an eine Datei anGeeignet für Protokolle
2>stderrSchreibt Fehlermeldungen in eine Dateistdout bleibt getrennt
2>>stderrHängt Fehlermeldungen anVorhandene Fehlerprotokolle bleiben erhalten
2>&1stderrLeitet stderr zum aktuellen stdout-ZielDie Reihenfolge der Umleitungen ist entscheidend
|stdout zu stdinVerbindet zwei Befehlestderr wird nicht automatisch übertragen

Sicherer und nachvollziehbarer Einsatz

  • Verwende > nur, wenn ein Überschreiben beabsichtigt ist.
  • Nutze >> für fortlaufende Protokolle und Ergebnisse, die erhalten bleiben sollen.
  • Speichere stderr getrennt, wenn Ergebnisse und Diagnosen unabhängig geprüft werden müssen.
  • Verwende für ein gemeinsames Protokoll die Reihenfolge befehl > datei 2>&1.
  • Prüfe Dateipfad, Zielverzeichnis und Schreibrechte, bevor du eine Umleitung ausführst.

Fehler bei Umleitungen verstehen

Die Fehlermeldung steht trotz > im Terminal

> betrifft nur stdout. Viele Fehlermeldungen werden nach stderr geschrieben und erscheinen deshalb weiterhin im Terminal. Verwende eine getrennte Umleitung oder führe beide Ströme zusammen:

befehl > ausgabe.txt 2> fehler.txt
befehl > ausgabe-und-fehler.txt 2>&1

Eine vorhandene Datei enthält nur noch neue Daten

Wahrscheinlich wurde > statt >> verwendet. > ersetzt den bisherigen Inhalt bereits beim Öffnen des Ziels. Für ein Protokoll ist meist folgende Variante richtig:

date >> protokoll.txt

Die gemeinsame Protokolldatei enthält nicht alle Fehler

Kontrolliere die Reihenfolge. Für ein gemeinsames Ziel verwende:

befehl > protokoll.txt 2>&1

Permission denied oder No such file or directory

Permission denied bedeutet meist, dass der Benutzer die Zieldatei nicht erstellen oder beschreiben darf. No such file or directory weist häufig auf ein fehlendes Zielverzeichnis oder einen falschen Pfad hin. Prüfe den Pfad, die vorhandenen Verzeichnisse und die Schreibrechte. Wähle gegebenenfalls ein Ziel, in dem dein Benutzer schreiben darf.

Fehlermeldungen werden nicht durch eine Pipe verarbeitet

Eine normale Pipe überträgt nur stdout. Soll stderr ebenfalls in die nächste Verarbeitungskette gelangen, führe die Ströme vor der Pipe zusammen:

befehl 2>&1 | grep problem

Wenn Fehler nicht verarbeitet, sondern nur separat protokolliert werden sollen, leite stderr stattdessen in eine eigene Datei um.

Prüfungsrelevante Merksätze

  • stdin hat den Dateideskriptor 0, stdout 1 und stderr 2.
  • Im Terminal zeigen stdin, stdout und stderr typischerweise auf Tastatur beziehungsweise Terminal, bleiben aber getrennte Ströme.
  • > überschreibt, >> hängt an.
  • 2> und 2>> betreffen stderr, nicht stdout.
  • | verbindet stdout des linken Befehls mit stdin des rechten Befehls.
  • 2>&1 führt stderr mit dem aktuellen stdout-Ziel zusammen; die Reihenfolge ist entscheidend.

Weitere Zusammenhänge findest du im Thema Datenströme in Linux.