UNIX Kommandos verkoppeln
|
Willemers Informatik-Ecke
Jedes Programm erledigt genau seine Aufgabe
UNIX-Kommandos wirken manchmal etwas spartanisch. Ihre Ausgaben sind nur auf
das beschränkt, was ihre Aufgabe ist. Während ls wirklich nur die
Dateinamen anzeigt, zeigt der analoge Befehl dir unter MS-DOS gleich
noch den Namen der Platte, die Anzahl der Dateien und wieviel Platz auf der
Platte noch frei ist. Der Grund dafür liegt nicht in erster Linie in der
Faulheit der UNIX-Programmierer, sondern darin, dass es zur UNIX-Philosophie
gehört, Programme zu kombinieren, um die gewünschten Informationen zu erhalten.
Die Daten, die ein Befehl erzeugt, sollten so gestaltet sein, dass sie von
einem anderen Programm weiterverarbeitet werden.
Programme kombinieren
Um auf das Beispiel mit der Anzahl der Dateien zurückzukommen,
würde man unter UNIX das Ergebnis von ls durch den Befehl
wc (wordcounter. Das Programm
zählt Worte.), bearbeiten lassen und erhielte damit die Anzahl der
aufgelisteten Dateien. Das Kommando dazu sieht so aus:
Als Kupplung zwischen den Befehlen wird die Ein- und Ausgabe der Programme
verwendet. Unter UNIX kann beides leicht umgeleitet und aneinander gehängt
werden. Hier wird die Ausgabe von ls in die Eingabe von wc
geschoben. Der senkrechte Strich soll eine Röhre (engl. pipe) darstellen.
Ein- und Ausgabe als Datenstrom
Ein- und Ausgabe sind Dateien
Die Tastatureingabe und die Bildschirmausgabe wird unter UNIX jeweils als Datei
aufgefasst. Die Standardeingabe heißt stdin und die Ausgabe
stdout. Um von der Tastatur ein Dateiende simulieren zu können, wird
die Tastenkombination ctrl-D am Anfang der Zeile verwendet.
ctrl-D ist die Dateiendekennung
Das ctrl-D ist bereits vom Abmelden her bekannt. Tatsächlich erwartet
die Shell
aus der Standardeingabedatei ihre Befehle und beendet sich, wenn diese Datei
beendet wird. Dieses Verhalten kann man natürlich dazu nutzen, mehrere
Shellbefehle in eine Datei zu schreiben und sie am Stück ausführen zu lassen.
Dazu ruft man die Shell mit dem Kommando sh und dieser Datei als
Parameter auf. Die Zusammenstellung mehrerer Befehle ist bereits ein einfaches
Programm. Abläufe, die immer gleich sind, kann man so leicht automatisieren.
Mit solchen Programmen wird sich das Kapitel Shellprogrammierung
befassen.
stderr: Kanal für Fehlermeldungen
Wie in den folgenden Abschnitten zu sehen ist, kann man stdout des
einen Programmes und stdin eines anderen Programmes miteinander
verkoppeln. Das zweite Programm verarbeitet also die Ausgaben des ersten
Programms als seine Eingabe. Da
Fehlermeldungen in diesem Datenstrom wenig hilfreich sind, gibt es neben
stdout noch einen separaten Ausgabekanal für die Fehlermeldungen
namens stderr.
Normalerweise zeigt auch dieser auf das Terminal. Auf
diese Weise kann man beliebig viele Programme aneinanderhängen, ohne sich
allzu große Sorgen darüber machen zu müssen, was im Fehlerfall einer
Komponente passiert. Die Fehlermeldung erscheint dennoch auf der Konsole,
während im Datenstrom nur gültige und verarbeitbare Daten fließen.
Umleitung
Durch Anhängen von < meinedatei an einen Befehl wird der Inhalt der
Datei meinedatei als
Eingabe verwandt. Die Datei meinedatei wird also für das Programm zum
stdin.
Durch Anhängen von > meinedatei wird die Ausgabe auf die Datei
meinedatei umgeleitet. Also wird wird die Datei meinedatei
für das Programm zum stdout.
Beides ist kombinierbar. Beispielsweise bedeutet
sort <eingabedatei >ausgabedatei
|
dass die Datei eingabedatei als Eingabe für den Sortierbefehl verwendet wird und dass
die Ergebnisse in der Datei ausgabedatei abgelegt werden.
Editor für Arme
Mit diesem Kommando kann man auch dann Textdateien erzeugen, wenn kein
Editor verfügbar ist.
Hier werden zwei Effekte ausgenutzt. Der erste ist die Umleitung der Ausgabe.
Die Ausgabe von cat wird nicht am Bildschirm angezeigt, sondern in eine Datei
geschrieben. Es wird also die Datei testdatei erzeugt. Der zweite Effekt
ist, dass keine Eingabedatei für cat angegeben wird. Dementsprechend
greift cat auf die
Standardeingabe, nämlich die von der Tastatur zu. Es wird also solange von der
Tastatur eingelesen, bis diese Eingabeeinheit am Ende der Datei ist. Das Ende
der Datei wird bei der Tastatur mit ctrl-D erzeugt.
Das Erzeugen von Dateien auf diese Weise ist natürlich hochgradig unbequem, da
es kaum Korrekturmöglichkeiten gibt.
Datei stutzen
Beim Umleiten einer Ausgabe wird die Zieldatei zunächst geleert.
Diesen Effekt kann man nutzen, wenn eine Protokolldatei zu groß wird.
Da solche Dateien von anderen Prozessen beschrieben werden, kann man sie
nicht einfach löschen. Auch wenn man die Datei unter diesem Namen wieder
erzeugt,
ist es nicht dieselbe Datei, die der Hintergrundprozess offen hatte.
Mit dem Größerzeichen und dem Dateinamen wird die Datei sofort auf 0 Byte
zurückgesetzt. Dabei ist die Datei nicht gelöscht worden. Es ist exakt die
Datei, die der Hintergrundprozess im Zugriff hatte.
>> hängt die Ausgabe an die Datei an
Nicht immer soll der Inhalt der Datei gelöscht werden, in die man die
Ausgabe umleitet. Verwendet man statt einem Größerzeichen zwei, so wird
die Ausgabe an die existierende Datei angehängt.
2> leitet stderr um
Um stderr umzuleiten, wird eine 2 vor das Größerzeichen geschrieben.
Dies ist
beispielsweise wichtig, wenn man die Fehlermeldungen eines Compilers in einer
Datei auffangen will.
cc mistprogramm.c 2>fehlerliste
|
Um stdout und stderr in die gleiche Datei umzuleiten, gibt
es je nach verwendeter Shell zwei Umleitungsoperatoren.
Bei der Kornshell wird an das Größerzeichen ein kaufmännisches Und mit einer
1 angehängt. Bei der C-Shell wird nur das kaufmännische
Und vor das Größerzeichen gestellt. Soll der Compiler des obigen
Beispiels Fehlermeldungen und Ausgaben in dieselbe Datei umleiten lauten die
alternativen Befehle:
cc mistprogramm.c 2>&1 fehlerliste
cc mistprogramm.c &> fehlerliste
|
/dev/null ist der Müllschlucker
Manchmal kann man mit den Ausgaben der Programme überhaupt nichts anfangen.
Für solche Zwecke hat UNIX ein Datengrab oder Mülleimer, der /dev/null
heißt. Alle Daten, die auf diese Pseudodatei umgeleitet werden, verschwinden
auf Nimmerwiedersehen.
Piping
seitenweises Blättern
Durch den senkrechten Strich | wird eine Pipe aufgebaut, die die Ausgabe des
links stehenden Kommandos auf die Eingabe des rechts stehenden Kommandos
umleitet. Programme, die ihre Anwendung typischerweise im Datenstrom einer Pipe
finden, nennt man Filter. Ein ganz typischer Filter ist das Programm
more. Um sich längere Verzeichnisse seitenweise anzusehen, wird
man eine Pipe zwischen ls -l und more verwenden:
Bedienung des more
Nach jeder Bildschirmseite erscheint die Meldung more. Mit der Leertaste kann
eine Seite weitergeblättert werden. Die Returntaste wirkt ein zeilenweises
blättern. Will man die Ausgabe beenden, gibt man ein q ein.
Bindestrich als Dateiname
Einige Programme geben ihre Ergebnisse nicht auf stdout aus, sondern
benutzen immer eine Ausgabedatei.
Dazu gehört beispielsweise das Datensicherungsprogramm
tar.
tar schreibt normalerweise auf das
Standardgerät zur Datensicherung. Auf Servern ist dies meist die Bandstation.
Allerdings kann man tar mit der Option -f dazu bringen,
in eine Datei zu schreiben.
In bestimmten Situationen soll das Programm aber in eine Pipe schreiben.
Damit in solchen Fällen eine Pipe hineingeschrieben werden kann,
braucht man einen Dateinamen für die Pipe, den man für die Pipe statt des
Dateinamens angeben kann.
An dieser Stelle wird ein Bindestrich als Synonym für stdin und
stdout verwendet. Diese Konstruktion ist beim
Kopieren von Verzeichnisbäumen mit tar
und beim Brennen von Verzeichnissen
auf CD zu sehen.
Datenabzweigung: tee
Manchmal kann man in einer Pipe auch die Zwischenergebnisse gut
gebrauchen. In diesem Fall kann man das Kommando tee
gefolgt von einem Dateinamen in die Pipe einfügen. Dann wird der
aktuelle Datenstrom in diese Datei abgezweigt, während trotzdem
die nächste Anwendung in der Pipe den Datenstrom unverändert
weiterverarbeiten kann. Beispiel:
In der Datei out wird man die Dateinamen des aktuellen Verzeichnisses
finden, während die Ausgabe des Befehls die Anzahl der Dateien
darstellt.
Das Programm tee bildet also das T-Stück im Datenstrom und zweigt
Daten in die angegebene Datei ab.
Verschachtelte Befehls-Argumente
Befehl im Befehl
Die Argumente eines Befehls können durch andere Prozesse erzeugt werden. Um
dies zu erreichen, wird statt des Arguments ein Befehl in rückwärtige
Hochkommata (backquotes) gesetzt werden. Von manchen UNIX Anwendern
wird dieses Zeichen auch Rückwärtsdüdel genannt. Leider kann ich für die
korrekte Schreibweise nicht garantieren.
Auf amerikanischen Tastaturen liegt sie rechts neben dem Apostroph.
Man findet diese Taste auf einer deutschen Tastatur rechts neben dem
ß in Kombination mit der Hochstelltaste.
Das Ergebnis dieses Befehls wird dem
eigentlichen Befehl als Argument zugeführt.
Beispiel:
In diesem Fall wird der Inhalt der Datei filelist mit cat
ausgegeben und so als Argumentliste dem ls zugeführt.
Man könnte die Datei filelist als Liste der Dateien zu einem
Programmierprojekt benutzen. Um diese zu übersetzen, könnte der Befehl
cc -o projekt `cat filelist`
|
abgesetzt werden. Eine Sicherung der Quelltexte könnte dann per
cp `cat filelist` /usr/projekt/backup
|
Alternativschreibweise in Klammern mit Dollar vorn
erfolgen. Leider sind die Backquotes im Ausdruck kaum von einem
Apostroph zu unterscheiden. Beide haben aber unter UNIX eine deutlich
unterschiedliche Bedeutung.
Als Alternativschreibweise bieten die meisten Shells an, den in Backquotes
stehenden Ausdruck einzuklammern und ein Dollarzeichen voranzustellen.
Damit sind die beiden untenstehenden Ausdrücke gleichbedeutend.
ls -l `cat filelist`
ls -l $(cat filelist)
|