In der Welt der Kommandozeile arbeiten Programme oft mit drei Standard-Datenströmen:
stdin): Hier empfängt ein Programm seine Eingabe (normalerweise von der Tastatur).stdout): Hierhin schickt ein Programm seine normale Ausgabe (normalerweise auf den Terminalbildschirm).stderr): Hierhin schickt ein Programm Fehlermeldungen (normalerweise auf den Terminalbildschirm).Erinnere dich daran, dass wir diese im Kapitel Pipelines und Befehlslisten eingeführt haben.
Pipelines kann man als eine Form der Umleitung betrachten: Die Standardausgabe eines Programms wird direkt an die Standardeingabe eines anderen geschickt. Pipelines haben wir bereits behandelt. In diesem Konzept geht es um die Umleitung in und aus Dateien.
Die Shell-Umleitung ist ein mächtiger Mechanismus, mit dem du das Ziel dieser Ströme änderst. Statt dass ein Programm von der Tastatur liest oder auf den Bildschirm schreibt, kannst du die Eingabe aus einer Datei umleiten oder die Ausgabe in eine Datei schicken. Das gibt dir viel Flexibilität und Kontrolle darüber, wie Programme mit Daten umgehen.
Hier sind die gebräuchlichsten Umleitungsoperatoren und was sie bewirken:
> (Ausgabeumleitung)Zweck: Die Standardausgabe (stdout) eines Befehls in eine Datei umleiten.
Verhalten:
Beispiel:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
Die Umleitung erfolgt bevor der Befehl ausgeführt wird. Das bedeutet, du kannst nicht in dieselbe Datei umleiten, aus der du lesen musst.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
Im zweiten Befehl des obigen Beispiels
>> (Ausgabe anhängen)Zweck: Die Standardausgabe (stdout) eines Befehls an eine Datei anhängen.
Verhalten:
Beispiel:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (Eingabeumleitung)Zweck: Die Standardeingabe (stdin) eines Befehls aus einer Datei umleiten.
Verhalten: Der Befehl liest seine Eingabe aus der angegebenen Datei statt von der Tastatur.
Beispiel:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (Fehlerumleitung):stderr) eines Befehls in eine Datei umleiten.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
Mit 2>> kannst du die Standardfehlerausgabe an eine Datei anhängen.
Es gibt auch Umleitungen, die stdin und stderr zusammenführen können.
Details findest du im Handbuch.
/dev/null/dev/null ist eine spezielle Datei, die
Man nennt sie manchmal auch „Bitbucket“. Sie ist nützlich, um Ausgaben oder Fehler zu unterdrücken.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
Du kannst mehrere Umleitungen gleichzeitig angeben.
some_command < input.txt > output.txt 2> error.txt
Eine Umleitung kann kopiert werden.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
Wenn du 2>&1 siehst, lies das als „leite stderr dorthin um, wohin stdout gerade jetzt zeigt“.
Bash verarbeitet Umleitungsanweisungen streng von links nach rechts. Das bedeutet, du kannst Folgendes machen:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
In der Shell-Programmierung und in Betriebssystemen wie Linux/Unix ist ein Dateideskriptor (File Descriptor, FD) eine nicht-negative Ganzzahl, die als Kennung oder Handle für eine geöffnete Datei oder eine E/A-Ressource (Eingabe/Ausgabe) dient. Stell es dir wie ein Etikett oder eine Referenznummer vor, mit der das Betriebssystem den Überblick über geöffnete Dateien und Datenströme behält.
Die Zahlen, die du auf der linken Seite von Umleitungen siehst, sind Dateideskriptoren.
Die Standard-E/A-Ströme bekommen die ersten drei Dateideskriptoren:
Neue Dateideskriptoren kannst du mit dem Befehl exec und Umleitungsoperatoren setzen oder anlegen.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
Diese Technik wirkt ziemlich verschachtelt, aber sie kann sehr nützlich sein, wenn dein Skript von einer anderen Software ausgeführt wird und diese die Standardausgabe automatisch abfängt.
Der Befehl bats, mit dem in diesem Track die Unit-Tests ausgeführt werden, funktioniert genau so: bats fängt die Standardausgabe und die Standardfehlerausgabe eines Tests ab, aber Debug-Meldungen an FD 3 werden auf dem Terminal angezeigt.
Warum ist Umleitung nützlich?
Shell-Umleitungen geben dir fein abgestufte Kontrolle darüber, wie Programme mit Daten umgehen. So kannst du komplexe Workflows aufbauen und Informationen effektiv verwalten.