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.
| Strom | Abkürzung | Dateideskriptor | Standardquelle oder Standardziel | Typischer Inhalt |
|---|---|---|---|---|
| Standardeingabe | stdin | 0 | Tastatur | Eingabedaten |
| Standardausgabe | stdout | 1 | Terminal | Reguläre Ergebnisse und Statusausgaben |
| Standardfehlerausgabe | stderr | 2 | Terminal | Fehlermeldungen 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
| Syntax | Betroffener Strom | Wirkung | Hinweis |
|---|---|---|---|
< | stdin | Liest eine Datei als Standardeingabe | Die Datei wird Quelle des Programms |
> | stdout | Schreibt in eine Datei | Vorhandener Inhalt wird ersetzt |
>> | stdout | Hängt an eine Datei an | Geeignet für Protokolle |
2> | stderr | Schreibt Fehlermeldungen in eine Datei | stdout bleibt getrennt |
2>> | stderr | Hängt Fehlermeldungen an | Vorhandene Fehlerprotokolle bleiben erhalten |
2>&1 | stderr | Leitet stderr zum aktuellen stdout-Ziel | Die Reihenfolge der Umleitungen ist entscheidend |
| | stdout zu stdin | Verbindet zwei Befehle | stderr 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>und2>>betreffen stderr, nicht stdout.|verbindet stdout des linken Befehls mit stdin des rechten Befehls.2>&1führt stderr mit dem aktuellen stdout-Ziel zusammen; die Reihenfolge ist entscheidend.
Weitere Zusammenhänge findest du im Thema Datenströme in Linux.