====== Ein- und Ausgaben beim Bashscript umleiten ====== Ein- und Ausgaben können umgeleitet werden Eine solche Umleitung ist für die beteiligten Prozesse transparent, d.h. dem Prozess ist es letztlich egal, woher er seine Eingaben bezieht und wohin er seine Ausgaben schreibt. Als Ziel bzw. Quelle einer jeden Umleitung kommen entweder Dateien in Frage oder aber andere Prozesse. In letzterem Fall spricht man auch von »Pipelining«. Zunächst fassen wir alle Möglichkeiten zur Umleitung von Ein- und Ausgaben zusammen: < datei Standardeingabe, Lesen aus »datei« > datei Standardausgabe, Schreiben in »datei« 2> datei Standardfehlerausgabe, Schreiben der Fehler in »datei« &> datei oder >& datei Standard- und Standardfehlerausgabe, Schreiben in »datei« >> datei Standardausgabe, Anhängen an »datei« [[http://www.linuxfibel.de/eaumleitung.htm]] ====== Ein-und Ausgabeumleitung ====== Die drei dem Terminal zugeordeneten Dateikanäle stdin, stdout und stderr können jederzeit auf Dateien umgeleitet werden. Den drei Standarddateien sind die Filehandles 0 (stdin), 1 (stdout) und 2 (stderr) zugeordnet. ===== Eingabeumleitung ===== Das Programm liest nun nicht mehr von der Tastatur (stdin), sondern aus einer Datei, bis das Dateiende erreicht ist. Die Eingabeumleitung erfolgt durch das Zeichen "<", gefolgt von einem Dateinamen. Kommando < Dateiname Statt z. B. beim write-Kommando den Text direkt einzugeben, kann auch einen Datei an ein anderes Terminal gesendet werden: write markus < Nachricht ===== Ausgabeumleitung ===== Die Ausgabe des Programms wird nicht auf dem Bildschirm (stdout) ausgegeben, sondern in einen Datei geschrieben. Die Ausgabeumleitung erfolgt durch das Zeichen ">", gefolgt von einem Dateinamen. Falls die Datei noch nicht vorhaden war, wird sie automatisch angelegt. Falls die Datei schon vorhanden ist, wird sie überschrieben, d. h. es wird immer ab dem Dateianfang geschrieben. Kommando > Dateiname Fehlermeldungen (stderr) erscheinen nach wie vor auf dem Bildschirm. Beispiel: Ausgabe der Verzeichnisbelegung in einen Datei: ls -l > info Umlenkung der Fehlerausgabe (stderr) Die Umleitung der Fehlerausgabe erfolgt genauso, wie die Ausgabeumleitung, jedoch wird hier die Zeichenfolge "2>" verwendet, da stderr die Handlenummer 2 hat. Kommando 2> Fehlerdatei (Die Umleitung der Standardausgabe ist nur die Kurzform von Kommando 1> Dateiname). Natürlich ist eine beliebige Kombination von Ein- und Ausgabeumleitung möglich, z. B. Kommando < Eingabedatei > Ausgabedatei 2> Fehlerdatei Anhängen von Infos an eine Datei Es ist auch möglich, die Ausgabe des Programms an eine bereits vorhandene Datei anzuhängen. Dazu wird des ">" doppelt geschrieben. Kommando >> Sammeldatei Dazu ein paar Beispiele: Dateiliste und aktive Benutzer in einen Datei schreiben: ls -l > liste who >> liste Dur Umleitung von Ein- und Ausgabe läßt sich auch unterdrücken. Für die Ausgabe schreibt man Kommando > /dev/null oder für die Fehlerausgabe Kommando 2> /dev/null. Beides läßt sich auch kombinieren: Kommando > Ergebnisdatei 2> /dev/null. Will man ein Programm mit einem beliebigen Eingabedatenstrom versorgen, schreibt man Kommando < /dev/zero. Die Umleitung von stout und stderr in dieselbe Datei würde prinzipiell eine zweimalige Angabe der Datei (eventuell mit einem langen Pfad) erfordern. Für die Standarddateien werden in solchen Fällen spezielle Platzhalter verwendet: &0 Standardeingabe &1 Standardausgabe &2 Standard-Fehlerausgabe Kommando > ausgabe 2>&1 Wenig bekannt ist der Bourne-Shell-Operator <>. Er öffnet eine Datei zum Lesen und Schreiben und verbindet sie mit der Standardeingabe. Fehlende Dateien legt er automatisch an, im Gegensatz zu > löscht er jedoch nicht den Inhalt bestehender Dateien. Gut eignet sich <> vor allem für den Zugriff auf Geräte, die eine bidirektionale Verbindung voraussetzen - etwa Terminals oder Modems. Die Bourne-Shell kann noch mehr: Man kann einen beliebigen Kommunikationskanal umlenken, indem er dessen Kennzahl direkt vor das Größer oder Kleiner-Zeichen schreibt. Wie schon erwähnt, steht '0' für die Standardeingabe, 'l' und '2' stehen für die Standard- beziehungsweise Fehlerausgabe. Allgemein gilt also: Mit den Bourne-Shell-Operatoren <& und >& lassen sich Ein- und Ausgabekanäle miteinander verbinden. Vor dem Operator darf die Nummer des umgeleiteten Kanals stehen, dahinter muß die des Quell- beziehungsweise Zielkanals folgen. Die häufigste Konstruktion >datei 2>&1 leitet Standard- und Fehlerausgabe in dieselbe Datei um. Michael Riepe beschreibt in iX 10/2002, im Artikel "Kreuz und quer - Ein- und Ausgabeumleitung in der Shell", S. 142 weitergehende Anwendungen von Umleitungen: Mehrere Umleitungen innerhalb eines Befehls führt die Shell nacheinander aus, und zwar in Schreibrichtung von links nach rechts. Stehen Umleitungen hinter einem zusammengesetzten Befehl, etwa einer Schleife, gelten sie für das gesamte Konstrukt; sie lassen sich jedoch innerhalb der Schleife durch weitere Umleitungen zeitweilig außer Kraft setzen. Es ist auch möglich, denselben Kanal in einem Befehl mehrmals umzuleiten. Dabei gilt, daß die jeweils zuletzt ausgeführte Ein- oder Ausgabeumleitung Vorrang hat. Das Kommando cat c >d kopiert den Inhalt der Datei b in die Datei d. Als Seiteneffekt legt es eine leere Datei c an oder löscht den Inhalt von c, falls die Datei schon existierte. Mitunter genügen die drei Standard-Kommunikationskanäle nicht, um eine Aufgabe zu erfüllen. Soll ein Skript etwa den Inhalt dreier Dateien miteinander vermengen, benötigt es zusätzliche Eingabekanäle. In der Bourne-Shell lassen sich weitere Kanäle mit den normalen Umleitungsoperatoren öffnen; der Benutzer muß lediglich die Nummer des gewünschten Kanals angeben. Mit den Umleitungsoperatoren <& und >& kann er die neuen Kanäle für einzelne Befehle öffnen, zum Beispiel: # Dateimischer while read X <&3 && read Y <&4 && read Z <&5 do echo $X $Y $Z done 3 Die Anzahl der offenen Kanäle ist durch die Shell oder das Betriebssystem begrenzt. Portable Skripte dürfen nur die Kanäle 0 bis 9 verwenden. Bourne-Shell-Benutzer verwenden eine Spezialform des Befehls exec: Stehen hinter dem Befehlswort nur Umleitungen, aber keine Argumente, leitet die Shell die gewünschten Kanäle permanent um. Ist man zum Beispiel an Fehlermeldungen nicht interessiert, kann man sie vernichten mit exec 2>/dev/null Soll eine Umleitung später aufgehoben werden, kann man den ursprünglichen Kanal duplizieren: exec 3<&0 &- einen Ausgabekanal.