Umleitungen: Unterschied zwischen den Versionen

Aus wiki.archlinux.de
Dongiovanni (Diskussion | Beiträge)
K Kategorie nicht vorhanden
KKeine Bearbeitungszusammenfassung
 
(9 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 5: Zeile 5:
Je nach Position an der ein Kanal angesprochen wird, hat er unterschiedliche Bezeichnungen, zudem werden die Kanäle je nach Position unterschiedlich referenziert.
Je nach Position an der ein Kanal angesprochen wird, hat er unterschiedliche Bezeichnungen, zudem werden die Kanäle je nach Position unterschiedlich referenziert.


<!-- Ne sorry, aber die Standard-Wiki-Tabelle ist hässlich und unübersichtlich dargestellt! -->
{| {{prettytable}}
<table border=0 rules="none" cellspacing="0" cellpadding="0" style="width:50%; margin-top:0.5em; margin-bottom:0.5em;">
!Kanal  !! Bezeichnung           !! Schreibweise
  <tr style="background-color:#babdb6; border-bottom:0.3em solid #f0f0f0;">
|-
    <td><strong>Kanal</strong></td>
|STDIN || Eingabeumleitung     || {{ic|<}} oder {{ic|<<}}
    <td><strong>Bezeichnung</strong></td>
|-
    <td><strong>Schreibweise</strong></td>
|STDIN || Standardeingabe       || {{ic|-}}
  </tr>
|-
  <tr style="background-color:#d3d7cf; border-bottom:0.3em solid #f0f0f0;">
|STDOUT || Ausgabeumleitung     || {{ic|>}} oder {{ic|>>}}
    <td>STDIN</td>
|-
    <td>Eingabeumleitung</td>
|STDOUT || Standardausgabe       || {{ic|-}}
    <td>< oder <<</td>
|-
  </tr>
|STDOUT || Standardausgabe-Kanal || {{ic|1}} oder {{ic|&1}}
  <tr style="background-color:#d3d7cf; border-bottom:0.3em solid #f0f0f0;">
|-
    <td>STDIN</td>
|STDERR || Standard-Fehlerkanal || {{ic|2}} oder {{ic|&2}}
    <td>Standardeingabe</td>
|}
    <td>-</td>
  </tr>
  <tr style="background-color:#d3d7cf; border-bottom:0.3em solid #f0f0f0;">
    <td>STDOUT</td>
    <td>Ausgabeumleitung</td>
    <td>> oder >></td>
  </tr>
  <tr style="background-color:#d3d7cf; border-bottom:0.3em solid #f0f0f0;">
    <td>STDOUT</td>
    <td>Standardausgabe</td>
    <td>-</td>
  </tr>
  <tr style="background-color:#d3d7cf; border-bottom:0.3em solid #f0f0f0;">
    <td>STDOUT</td>
    <td>Standardausgabe-Kanal</td>
    <td>1 oder &1</td>
  </tr>
  <tr style="background-color:#d3d7cf; border-bottom:0.3em solid #f0f0f0;">
    <td>STDERR</td>
    <td>Standard-Fehlerkanal</td>
    <td>2 oder &2</td>
  </tr>
</table>


In diesem Artikel werden der Standardeingabe-Kanal und der Standardausgabe-Kanal, so wie der Standard-Fehlerkanal immer als STDIN, STDOUT und STDERR bezeichnet.
In diesem Artikel werden der Standardeingabe-Kanal und der Standardausgabe-Kanal, so wie der Standard-Fehlerkanal immer als STDIN, STDOUT und STDERR bezeichnet.
Zeile 53: Zeile 30:
  ls -al > output
  ls -al > output


Dies schreibt die Namen der Dateien und Verzeichnisse im aktuellen Verzeichnis in die Datei „output“. Wenn die Datei noch nicht existiert, wird sie angelegt. Falls sie bereits existiert, wird sie überschrieben. Wenn man möchte, dass die Ausgabe an die Datei angehängt wird, benutzt man >>, anstatt >
Dies schreibt die Namen der Dateien und Verzeichnisse im aktuellen Verzeichnis in die Datei {{ic|output}}. Wenn die Datei noch nicht existiert, wird sie angelegt. Falls sie bereits existiert, wird sie überschrieben. Wenn man möchte, dass die Ausgabe an die Datei angehängt wird, benutzt man {{ic|>>}}, anstatt {{ic|>}}


  ls -al >> output
  ls -al >> output
Zeile 59: Zeile 36:
  >> output ls -al
  >> output ls -al


Die zweite Zeile bewirkt das Selbe, wie die erste Zeile, soll hier aber nur als Beispiel dafür dienen, dass es relativ irrelevant ist, an welcher Stelle eine Umleitung definiert wird (hier vor dem eigentlich umzuleitenden Befehl).
Die zweite Zeile bewirkt das Selbe wie die erste Zeile, soll hier aber nur als Beispiel dafür dienen, dass es relativ irrelevant ist, an welcher Stelle eine Umleitung definiert wird (hier vor dem eigentlich umzuleitenden Befehl).


Die einfache Umleitung ohne Angabe des Kanals leitet immer STDOUT entsprechend um. Fehlermeldungen, die nach STDERR geschrieben werden, werden damit nicht umgeleitet. Es ist natürlich möglich, diese Fehlermeldungen auch zumzuleiten
Die einfache Umleitung ohne Angabe des Kanals leitet immer STDOUT entsprechend um. Fehlermeldungen, die nach STDERR geschrieben werden, werden damit nicht umgeleitet. Es ist natürlich möglich, diese Fehlermeldungen auch umzuleiten


  command 2>> error.log
  command 2>> error.log


Dies schreibt alle Fehlermeldungen des Programms „command“ in die Datei „error.log“, wobei die Datei nicht überschrieben, sondern die Ausgabe immer an die Datei angehängt wird. Will man jetzt auch noch die Standard-Ausgabe umleiten, zum Beispiel nach /dev/null, weil das Programm als [[Cronjob]] läuft, und die Ausgabe unwichtig ist, geht dies mit folgendem Aufruf
Dies schreibt alle Fehlermeldungen des Programms {{ic|command}} in die Datei {{ic|error.log}}, wobei die Datei nicht überschrieben, sondern die Ausgabe immer an die Datei angehängt wird. Will man jetzt auch noch die Standard-Ausgabe umleiten, zum Beispiel nach /dev/null, weil das Programm als [[Cronjob]] läuft, und die Ausgabe unwichtig ist, geht dies mit folgendem Aufruf


  command > /dev/null 2>> error.log
  command > /dev/null 2>> error.log


Dies schreibt STDOUT nach [[/dev/null]], und STDERR in die Datei „error.log“. Es besteht auch die Möglichkeit, Kanäle „ineinanderzuleiten“. Dies kann nützlich sein, wenn man STDERR und STDOUT an die selbe Stelle umleiten möchte.
Dies schreibt STDOUT nach [[/dev/null]], und STDERR in die Datei {{ic|error.log}}. Es besteht auch die Möglichkeit, Kanäle „ineinanderzuleiten“. Dies kann nützlich sein, wenn man STDERR und STDOUT an die selbe Stelle umleiten möchte.


  command 2>&1> /dev/null
  command 2>&1> /dev/null
  command > /dev/null 2>&1
  command > /dev/null 2>&1


Dies leitet STDERR nach STDOUT (STDOUT wird hier mittels &1“ referenziert. STDERR würde an dieser Stelle analog dazu mit &2“ referenziert werden) um. STDOUT wird nach /dev/null“ umgeleitet. Das Resultat ist, dass weder Standard-Meldungen noch Fehlermeldungen von „command“ ausgegeben werden.
Dies leitet STDERR nach STDOUT (STDOUT wird hier mittels {{ic|&1}} referenziert. STDERR würde an dieser Stelle analog dazu mit {{ic|&2}} referenziert werden) um. STDOUT wird nach {{ic|/dev/null}} umgeleitet. Das Resultat ist, dass weder Standard-Meldungen noch Fehlermeldungen von {{ic|command}} ausgegeben werden.


Die zweite Zeile ist eine gängige, alternative Schreibweise dieses Aufrufs. Durch > /dev/null“ wird die STDOUT nach /dev/null“ geleitet, durch „2>&1“ wird STDERR nach STDOUT geleitet (das ja nach /dev/null“ geleitet wird).
Die zweite Zeile ist eine gängige, alternative Schreibweise dieses Aufrufs. Durch {{ic|> /dev/null}} wird die STDOUT nach {{ic|/dev/null}} geleitet, durch {{ic|2>&1}} wird STDERR nach STDOUT geleitet (das ja nach {{ic|/dev/null}} geleitet wird).


Alternativ kann man die Ausgabe auch in eine Datei umleiten. Es besteht ebenfalls die Möglichkeit, die zweite Umleitung ganz weg zu lassen.
Alternativ kann man die Ausgabe auch in eine Datei umleiten. Es besteht ebenfalls die Möglichkeit, die zweite Umleitung ganz weg zu lassen.
Zeile 89: Zeile 66:
  command < input
  command < input


Dies leitet den Inhalt der Datei „input“ an das Programm „command“ weiter. Wie dieses Programm damit umgeht, ist dem Programmier des Programms überlassen. Wenn ein Programm keine derartigen Umleitungen annimmt, passiert für gewöhnlich gar nichts. Eine weitere Methode ist die Umleitung mittels <<EOF“.
Dies leitet den Inhalt der Datei {{ic|input}} an das Programm {{ic|command}} weiter. Wie dieses Programm damit umgeht, ist dem Programmierer des Programms überlassen. Wenn ein Programm keine derartigen Umleitungen annimmt, passiert für gewöhnlich gar nichts. Eine weitere Methode ist die Umleitung mittels {{ic|<<EOF}}.


  command <<EOF
  command <<EOF
Zeile 98: Zeile 75:
  > EOF
  > EOF


Dies übergibt dem Programm „command“ die Zeilen 1 bis N in dieser Reihenfolge, jeweils als eigenständige Eingabe. Beim Schlüsselwort „EOF“ wird die Eingabeumleitung beendet. Statt „EOF“ kann man nahezu beliebige Schlüsselwörter verwenden, „EOF“ hat sich aber eingebürgert. Eine konkrete Anwendung könnte zum Beispiel ein Backup einer MySQL-Datenbank sein.
Dies übergibt dem Programm {{ic|command}} die Zeilen 1 bis N in dieser Reihenfolge, jeweils als eigenständige Eingabe. Beim Schlüsselwort {{ic|EOF}} wird die Eingabeumleitung beendet. Statt {{ic|EOF}} kann man nahezu beliebige Schlüsselwörter verwenden, {{ic|EOF}} hat sich aber eingebürgert. Eine konkrete Anwendung könnte zum Beispiel ein Backup einer MySQL-Datenbank sein.


  mysql -uUSER -pPASSWORD <<EOF
  mysql -uUSER -pPASSWORD <<EOF
Zeile 111: Zeile 88:


== Pipes ==
== Pipes ==
Mittels Pipes wird die Ausgabe eines Programms an ein anderes Programm weitergereicht. Das folgende Beispiel ist eigentlich ein Negativbeispiel, da [[grep]] bereits selbst über so eine Funktionalität verfügt, wird allerdings immer wieder gern hergenommen, um die Funktionsweise von Pipes zu demonstrieren, da es einfach und gut nachvollziehbar ist.
Mittels Pipes wird die Ausgabe eines Programms an ein anderes Programm weitergereicht. Das folgende Beispiel ist eigentlich ein Negativbeispiel, da grep bereits selbst über so eine Funktionalität verfügt, wird allerdings immer wieder gern hergenommen, um die Funktionsweise von Pipes zu demonstrieren, da es einfach und gut nachvollziehbar ist.


  cat file | grep inhalt
  cat file | grep inhalt


Durch „cat file“ wird der Inhalt der Datei „file“ ausgegeben. Die Ausgabe wird an „grep“ weitergeleitet, mittels dem die Ausgabe von „cat“, die nun Eingabe von „grep“ geworden ist, nach dem Wort „inhalt“ durchsucht wird. Es werden nun nur Zeilen ausgegeben, in denen „inhalt“ steht.
Durch {{ic|cat file}} wird der Inhalt der Datei {{ic|file}} ausgegeben. Die Ausgabe wird an {{ic|grep}} weitergeleitet, mittels dem die Ausgabe von {{ic|cat}}, die nun Eingabe von {{ic|grep}} geworden ist, nach dem Wort {{ic|inhalt}} durchsucht wird. Es werden nun nur Zeilen ausgegeben, in denen {{ic|inhalt}} steht.


Nur der Vollständigkeit halber, dies geht auch ohne cat:
Nur der Vollständigkeit halber, dies geht auch ohne cat:
Zeile 123: Zeile 100:
Einige Programme behandeln STDIN und STDOUT in Verbindung mit Pipes ein wenig anders. Generell muss man hier die [[Manpage]] des jeweiligen Programms lesen, an welcher Stelle STDIN und STDOUT berücksichtigt werden, dann allerdings werden beide durch ein Minus-Zeichen angesprochen.
Einige Programme behandeln STDIN und STDOUT in Verbindung mit Pipes ein wenig anders. Generell muss man hier die [[Manpage]] des jeweiligen Programms lesen, an welcher Stelle STDIN und STDOUT berücksichtigt werden, dann allerdings werden beide durch ein Minus-Zeichen angesprochen.


Ein konkretes Beispiel könnte das Aktualisieren eines Wallpapers sein. Das Wallpaper wird automatisch im Internet regelmäßig durch ein neues Wallpaper an selber Position ersetzt. Anstatt nun manuell jedes Mal das Wallpaper herunterzuladen und manuell jedes Mal einzustellen, kann man dies mittels [[wget]] und „display“ aus dem [[ImageMagick]]-Paket machen.
Ein konkretes Beispiel könnte das Aktualisieren eines Wallpapers sein. Das Wallpaper wird automatisch im Internet regelmäßig durch ein neues Wallpaper an selber Position ersetzt. Anstatt nun manuell jedes Mal das Wallpaper herunterzuladen und manuell jedes Mal einzustellen, kann man dies mittels wget und {{ic|display}} aus dem [[ImageMagick]]-Paket machen.


  wget http://example.com/zufallswallpaper.png -O - | display -window root -
  wget <nowiki>http://example.com/zufallswallpaper.png</nowiki> -O - | display -window root -


Hier wird durch wget das Wallpaper heruntergeladen. Anstatt das Wallpaper standardmäßig abzuspeichern wird es mittels -O“ unter einer anderen Bezeichnung gespeichert, in diesem Fall ist dies die Standard-Ausgabe. Die Meldungen die wget sonst noch ausgibt, werden dabei nicht mit ausgegeben, sondern lediglich die heruntergeladene Datei.
Hier wird durch wget das Wallpaper heruntergeladen. Anstatt das Wallpaper standardmäßig abzuspeichern wird es mittels {{ic|-O}} unter einer anderen Bezeichnung gespeichert, in diesem Fall ist dies die Standard-Ausgabe. Die Meldungen die wget sonst noch ausgibt, werden dabei nicht mit ausgegeben, sondern lediglich die heruntergeladene Datei.


Nach der Pipe wird „display“ aufgerufen, durch -window root“ wird definiert, dass es das Bild auf dem Root-Fenster anzeigen soll, dies ist der Desktop. Durch -wird hier die Standard-Eingabe referenziert. In der Standard-Eingabe befindet sich das, was wget davor in seine Standard-Ausgabe geschrieben hat.
Nach der Pipe wird {{ic|display}} aufgerufen, durch {{ic|-window root}} wird definiert, dass es das Bild auf dem Root-Fenster anzeigen soll, dies ist der Desktop. Durch {{ic|-}} wird hier die Standard-Eingabe referenziert. In der Standard-Eingabe befindet sich das, was wget davor in seine Standard-Ausgabe geschrieben hat.


=== FIFO-Pipes ===
=== FIFO-Pipes ===
FIFO steht für „'''F'''irst '''I'''n '''F'''irst '''O'''ut“ (sinngemäß „Was zuerst eingegeben wird, wird zuerst wieder ausgegeben“). FIFO-Pipes können als Zwischenschritt genutzt werden, wenn ein Programm nicht mittels Ein-/Ausgabeiumleitung oder herkömmlicher Pipes verwendet werden kann, oder die Verwendung von Pipes aufgrund technischer Umstände nicht möglich ist.
FIFO steht für „'''F'''irst '''I'''n '''F'''irst '''O'''ut“ (sinngemäß „Was zuerst eingegeben wird, wird zuerst wieder ausgegeben“). FIFO-Pipes können als Zwischenschritt genutzt werden, wenn ein Programm nicht mittels Ein-/Ausgabeumleitung oder herkömmlicher Pipes verwendet werden kann, oder die Verwendung von Pipes aufgrund technischer Umstände nicht möglich ist.


==== Übertragene Darstellung ====
==== Übertragene Darstellung ====
Zeile 139: Zeile 116:
Das Rohr bleibt dort so lange verschlossen, bis ein zweites Programm auf die FIFO-Pipe zugreift. Das zweite Programm öffnet den Deckel, und nimmt die Ausgabe des ersten Programms in der Reihenfolge in Empfang, wie sie das erste Programm in das Rohr geschoben hat. Die FIFO-Pipe ist nun offen.
Das Rohr bleibt dort so lange verschlossen, bis ein zweites Programm auf die FIFO-Pipe zugreift. Das zweite Programm öffnet den Deckel, und nimmt die Ausgabe des ersten Programms in der Reihenfolge in Empfang, wie sie das erste Programm in das Rohr geschoben hat. Die FIFO-Pipe ist nun offen.


Das Programm, dass die Daten in Empfang nimmt, macht dies so lange, wie der „Deckel“ des eingebenden Programms geöffnet ist. Der Deckel dieses Programms schließt sich, wenn es alle Daten in das Rohr geschoben hat. Die FIFO-Pipe ist dann geschlossen. Das empfangende Programm registriert dies, und schließt die seinen Deckel ebenfalls.
Das Programm, das die Daten in Empfang nimmt, macht dies so lange, wie der „Deckel“ des eingebenden Programms geöffnet ist. Der Deckel dieses Programms schließt sich, wenn es alle Daten in das Rohr geschoben hat. Die FIFO-Pipe ist dann geschlossen. Das empfangende Programm registriert dies, und schließt die seinen Deckel ebenfalls.


Der Vergleich hinkt ein wenig, da alles in dem „Rohr“ in praktisch Echtzeit geschieht, und auch nichts in das Rohr „hineingeschoben“ wird, sondern das eine Programm einfach so lange mit der Ausgabe wartet, bis das andere Programm die Eingabe anfordert.
Der Vergleich hinkt ein wenig, da alles in dem „Rohr“ in praktisch Echtzeit geschieht, und auch nichts in das Rohr „hineingeschoben“ wird, sondern das eine Programm einfach so lange mit der Ausgabe wartet, bis das andere Programm die Eingabe anfordert.
Zeile 150: Zeile 127:
  cat fifopipe
  cat fifopipe


Diese (eigentlich unnütze und nur der Demonstration dienende) Verwendung der FIFO-Pipe macht folgendes: Zuerst wird die FIFO-Pipe angelegt, dann wird die ausgabe von „ls -l /an diese FIFO-Pipe gesendet. Nun wird mittels „cat“ die Pipe ausgegeben. Man sieht nun die Ausgabe von „ls -l /.
Diese (eigentlich unnütze und nur der Demonstration dienende) Verwendung der FIFO-Pipe macht folgendes: Zuerst wird die FIFO-Pipe angelegt, dann wird die Ausgabe von {{ic|ls -l /}} an diese FIFO-Pipe gesendet. Nun wird mittels {{ic|cat}} die Pipe ausgegeben. Man sieht nun die Ausgabe von {{ic|ls -l /}}.


Wenn man nun noch mal mittels „cat“ die Inhalte der FIFO-Pipe ausgeben will, bekommt man nichts zurück, da der „Deckel“ auf der „anderen Seite“ ja nicht „geöffnet“ ist. Erst wenn man „auf der anderen Seite“ (zum Beispiel durch ein weiteres „ls -l /, das man in die FIFO-Pipe umleitet) wieder etwas „in das Rohr schiebt“, erhält man eine Ausgabe.
Wenn man nun noch mal mittels {{ic|cat}} die Inhalte der FIFO-Pipe ausgeben will, bekommt man nichts zurück, da der {{ic|Deckel}} auf der {{ic|anderen Seite}} ja nicht {{ic|geöffnet}} ist. Erst wenn man {{ic|auf der anderen Seite}} (zum Beispiel durch ein weiteres {{ic|ls -l /}}, das man in die FIFO-Pipe umleitet) wieder etwas {{ic|in das Rohr schiebt}}, erhält man eine Ausgabe.


FIFO-Dateien benutzen zum Weiterleiten der Inhalte Dateisystemfunktionen, normale Pipes benutzen Kernel-interne Puffer, wodurch diese Methode schneller ist. FIFO-Pipes können über Prozessgrenzen hinweg verwendet werden, wohingegen Pipes nur innerhalb des selben Elterprozesses verwendet werden können.  
FIFO-Dateien benutzen zum Weiterleiten der Inhalte Dateisystemfunktionen, normale Pipes benutzen Kernel-interne Puffer, wodurch diese Methode schneller ist. FIFO-Pipes können über Prozessgrenzen hinweg verwendet werden, wohingegen Pipes nur innerhalb des selben Elterprozesses verwendet werden können.


== Siehe auch ==
== Siehe auch ==
* Manpage „stdio“ (vor allem für Programmierer interessant)
* Manpage {{ic|stdio}} (vor allem für Programmierer interessant)
* [[bash]]
* [[bash]]



Aktuelle Version vom 4. Januar 2022, 09:47 Uhr

Eine der Stärken von Linux ist, dass Ein- und Ausgabe von Programmen umgeleitet werden können. Es gibt zwei wichtige Ausgabeleitungen (Kanäle genannt), dies sind STDERR, auf das alle Fehlermeldungen ausgegeben werden und STDOUT, auf das alle normalen Programm-Ausgaben ausgegeben werden. Zusätzlich gibt es noch den Standardeingabe-Kanal STDIN.

Bezeichnungen

Je nach Position an der ein Kanal angesprochen wird, hat er unterschiedliche Bezeichnungen, zudem werden die Kanäle je nach Position unterschiedlich referenziert.

Kanal Bezeichnung Schreibweise
STDIN Eingabeumleitung < oder <<
STDIN Standardeingabe -
STDOUT Ausgabeumleitung > oder >>
STDOUT Standardausgabe -
STDOUT Standardausgabe-Kanal 1 oder &1
STDERR Standard-Fehlerkanal 2 oder &2

In diesem Artikel werden der Standardeingabe-Kanal und der Standardausgabe-Kanal, so wie der Standard-Fehlerkanal immer als STDIN, STDOUT und STDERR bezeichnet.

Ausgabeumleitung

Prinzipiell können alle Ausgaben von Programmen entweder in eine Datei geschrieben, oder als Eingabe für weitere Programme verwendet werden. Die Angabe zur Umleitung kann zwar theoretisch an jeder Stelle eines Befehls gemacht werden, aus Gründen der Übersicht und der Logik sollte man eine Ausgabeumleitung aber nicht vor einer Eingabeumleitung oder dem eigentlichen Befehl definieren.

Der einfachste Fall einer Ausgabeumleitung ist das Umleiten von STDOUT in eine Textdatei, um so zum Beispiel eine Dateiliste zu erhalten.

ls -al > output

Dies schreibt die Namen der Dateien und Verzeichnisse im aktuellen Verzeichnis in die Datei output. Wenn die Datei noch nicht existiert, wird sie angelegt. Falls sie bereits existiert, wird sie überschrieben. Wenn man möchte, dass die Ausgabe an die Datei angehängt wird, benutzt man >>, anstatt >

ls -al >> output

>> output ls -al

Die zweite Zeile bewirkt das Selbe wie die erste Zeile, soll hier aber nur als Beispiel dafür dienen, dass es relativ irrelevant ist, an welcher Stelle eine Umleitung definiert wird (hier vor dem eigentlich umzuleitenden Befehl).

Die einfache Umleitung ohne Angabe des Kanals leitet immer STDOUT entsprechend um. Fehlermeldungen, die nach STDERR geschrieben werden, werden damit nicht umgeleitet. Es ist natürlich möglich, diese Fehlermeldungen auch umzuleiten

command 2>> error.log

Dies schreibt alle Fehlermeldungen des Programms command in die Datei error.log, wobei die Datei nicht überschrieben, sondern die Ausgabe immer an die Datei angehängt wird. Will man jetzt auch noch die Standard-Ausgabe umleiten, zum Beispiel nach /dev/null, weil das Programm als Cronjob läuft, und die Ausgabe unwichtig ist, geht dies mit folgendem Aufruf

command > /dev/null 2>> error.log

Dies schreibt STDOUT nach /dev/null, und STDERR in die Datei error.log. Es besteht auch die Möglichkeit, Kanäle „ineinanderzuleiten“. Dies kann nützlich sein, wenn man STDERR und STDOUT an die selbe Stelle umleiten möchte.

command 2>&1> /dev/null
command > /dev/null 2>&1

Dies leitet STDERR nach STDOUT (STDOUT wird hier mittels &1 referenziert. STDERR würde an dieser Stelle analog dazu mit &2 referenziert werden) um. STDOUT wird nach /dev/null umgeleitet. Das Resultat ist, dass weder Standard-Meldungen noch Fehlermeldungen von command ausgegeben werden.

Die zweite Zeile ist eine gängige, alternative Schreibweise dieses Aufrufs. Durch > /dev/null wird die STDOUT nach /dev/null geleitet, durch 2>&1 wird STDERR nach STDOUT geleitet (das ja nach /dev/null geleitet wird).

Alternativ kann man die Ausgabe auch in eine Datei umleiten. Es besteht ebenfalls die Möglichkeit, die zweite Umleitung ganz weg zu lassen.

command 2>&1

Dies leitet STDERR auf STDOUT um. Damit kann man nun mittels Pipe (siehe unten) die Standard-Ausgabe und die Fehlermeldungen in anderen Programmen als Eingabe benutzen.

Eingabeumleitung

Genau so, wie man Ausgaben umleiten kann, kann man auch Eingaben umleiten. Genauer gesagt kann man andere Eingabekanäle als STDIN verwenden, bzw. auf andere Art über STDIN etwas an ein Programm senden.

command < input

Dies leitet den Inhalt der Datei input an das Programm command weiter. Wie dieses Programm damit umgeht, ist dem Programmierer des Programms überlassen. Wenn ein Programm keine derartigen Umleitungen annimmt, passiert für gewöhnlich gar nichts. Eine weitere Methode ist die Umleitung mittels <<EOF.

command <<EOF
> Zeile 1
> Zeile 2
> Zeile 3
> Zeile N
> EOF

Dies übergibt dem Programm command die Zeilen 1 bis N in dieser Reihenfolge, jeweils als eigenständige Eingabe. Beim Schlüsselwort EOF wird die Eingabeumleitung beendet. Statt EOF kann man nahezu beliebige Schlüsselwörter verwenden, EOF hat sich aber eingebürgert. Eine konkrete Anwendung könnte zum Beispiel ein Backup einer MySQL-Datenbank sein.

mysql -uUSER -pPASSWORD <<EOF
flush tables with read lock;
system lvcreate -l100%FREE -s -n dbbackup /dev/vgmysql/mysql;
unlock tables;
EOF

Dieser Aufruf sperrt die Datenbank für Schreibzugriffe, erstellt durch einen MySQL-internen Systemaufruf einen LVM-Snapshot an angegebener Position, und gibt die Tabellen wieder frei. Mittels weiterer Programme kann nun mit dem Snapshot gearbeitet werden (Backup erstellen, etc.), ohne, dass die eigentliche Tabelle beeinflusst wird.

Per Eingabeumleitung werden hier drei Befehle an den MySQL-client gesendet. Dieser interpretiert die Befehle so, als wenn sie direkt eingegeben worden wären.

Pipes

Mittels Pipes wird die Ausgabe eines Programms an ein anderes Programm weitergereicht. Das folgende Beispiel ist eigentlich ein Negativbeispiel, da grep bereits selbst über so eine Funktionalität verfügt, wird allerdings immer wieder gern hergenommen, um die Funktionsweise von Pipes zu demonstrieren, da es einfach und gut nachvollziehbar ist.

cat file | grep inhalt

Durch cat file wird der Inhalt der Datei file ausgegeben. Die Ausgabe wird an grep weitergeleitet, mittels dem die Ausgabe von cat, die nun Eingabe von grep geworden ist, nach dem Wort inhalt durchsucht wird. Es werden nun nur Zeilen ausgegeben, in denen inhalt steht.

Nur der Vollständigkeit halber, dies geht auch ohne cat:

grep inhalt file

Einige Programme behandeln STDIN und STDOUT in Verbindung mit Pipes ein wenig anders. Generell muss man hier die Manpage des jeweiligen Programms lesen, an welcher Stelle STDIN und STDOUT berücksichtigt werden, dann allerdings werden beide durch ein Minus-Zeichen angesprochen.

Ein konkretes Beispiel könnte das Aktualisieren eines Wallpapers sein. Das Wallpaper wird automatisch im Internet regelmäßig durch ein neues Wallpaper an selber Position ersetzt. Anstatt nun manuell jedes Mal das Wallpaper herunterzuladen und manuell jedes Mal einzustellen, kann man dies mittels wget und display aus dem ImageMagick-Paket machen.

wget http://example.com/zufallswallpaper.png -O - | display -window root -

Hier wird durch wget das Wallpaper heruntergeladen. Anstatt das Wallpaper standardmäßig abzuspeichern wird es mittels -O unter einer anderen Bezeichnung gespeichert, in diesem Fall ist dies die Standard-Ausgabe. Die Meldungen die wget sonst noch ausgibt, werden dabei nicht mit ausgegeben, sondern lediglich die heruntergeladene Datei.

Nach der Pipe wird display aufgerufen, durch -window root wird definiert, dass es das Bild auf dem Root-Fenster anzeigen soll, dies ist der Desktop. Durch - wird hier die Standard-Eingabe referenziert. In der Standard-Eingabe befindet sich das, was wget davor in seine Standard-Ausgabe geschrieben hat.

FIFO-Pipes

FIFO steht für „First In First Out“ (sinngemäß „Was zuerst eingegeben wird, wird zuerst wieder ausgegeben“). FIFO-Pipes können als Zwischenschritt genutzt werden, wenn ein Programm nicht mittels Ein-/Ausgabeumleitung oder herkömmlicher Pipes verwendet werden kann, oder die Verwendung von Pipes aufgrund technischer Umstände nicht möglich ist.

Übertragene Darstellung

FIFO-Pipes kann man sich am besten als ein Rohr vorstellen. Auf beiden Seiten dieses Rohrs befinden sich Deckel. Wenn ein Programm nun auf einen FIFO-Pipe zugreift, wird der Deckel geöffnet, und das Programm schiebt die Ausgabe in das Rohr, bis die Ausgabe auf der anderen Seite an den Deckel stößt, dann wartet es.

Das Rohr bleibt dort so lange verschlossen, bis ein zweites Programm auf die FIFO-Pipe zugreift. Das zweite Programm öffnet den Deckel, und nimmt die Ausgabe des ersten Programms in der Reihenfolge in Empfang, wie sie das erste Programm in das Rohr geschoben hat. Die FIFO-Pipe ist nun offen.

Das Programm, das die Daten in Empfang nimmt, macht dies so lange, wie der „Deckel“ des eingebenden Programms geöffnet ist. Der Deckel dieses Programms schließt sich, wenn es alle Daten in das Rohr geschoben hat. Die FIFO-Pipe ist dann geschlossen. Das empfangende Programm registriert dies, und schließt die seinen Deckel ebenfalls.

Der Vergleich hinkt ein wenig, da alles in dem „Rohr“ in praktisch Echtzeit geschieht, und auch nichts in das Rohr „hineingeschoben“ wird, sondern das eine Programm einfach so lange mit der Ausgabe wartet, bis das andere Programm die Eingabe anfordert.

Verwendung

Wenn man eine FIFO-Pipe verwenden will, muss diese zuerst angelegt werden. Danach kann man sie ganz normal als Ausgabeumleitungs-Ziel verwenden.

mkfifo fifopipe
ls -l / > fifopipe &
cat fifopipe

Diese (eigentlich unnütze und nur der Demonstration dienende) Verwendung der FIFO-Pipe macht folgendes: Zuerst wird die FIFO-Pipe angelegt, dann wird die Ausgabe von ls -l / an diese FIFO-Pipe gesendet. Nun wird mittels cat die Pipe ausgegeben. Man sieht nun die Ausgabe von ls -l /.

Wenn man nun noch mal mittels cat die Inhalte der FIFO-Pipe ausgeben will, bekommt man nichts zurück, da der Deckel auf der anderen Seite ja nicht geöffnet ist. Erst wenn man auf der anderen Seite (zum Beispiel durch ein weiteres ls -l /, das man in die FIFO-Pipe umleitet) wieder etwas in das Rohr schiebt, erhält man eine Ausgabe.

FIFO-Dateien benutzen zum Weiterleiten der Inhalte Dateisystemfunktionen, normale Pipes benutzen Kernel-interne Puffer, wodurch diese Methode schneller ist. FIFO-Pipes können über Prozessgrenzen hinweg verwendet werden, wohingegen Pipes nur innerhalb des selben Elterprozesses verwendet werden können.

Siehe auch

  • Manpage stdio (vor allem für Programmierer interessant)
  • bash

Weblinks