Kapitel 2

Die Shell

IN DIESEM KAPITEL

  • Wie die Shell die Eingaben interpretiert und umsetzt
  • Datenströme umlenken und auswerten
  • Aus Befehle werden Skripte und eine einfache Programmiersprache

Der Kommandointerpreter von UNIX, dem Vorgänger von Linux, heißt traditionsgemäß Shell. Die erste Shell auf den ersten UNIX-Systemen stammte von einem Herrn Bourne. Dann fühlte sich jeder zweite Informatik-Student berufen, eine eigene Shell mit vielen tollen Features und eigener Syntax zu erschaffen. Dann wurden die Features zusammengefasst und erweitert, aber in ihrer Syntax wieder auf die ursprünglich von Herrn Bourne entwickelte Shell zurückgeführt. Daher trägt diese Shell den Namen bash (Bourne Again Shell). Diese ist inzwischen der Quasi-Standard unter Linux.

Starten der Shell

Eine Shell können Sie auf verschiedene Arten erlangen:

  • Jedes Linux hat mehrere virtuelle Terminals, über die Sie sich einloggen können. Sie erreichen diese über die Tastenkombinationen ++ bis ++. Mit ++ erreichen Sie wieder Ihre grafische Oberfläche.
  • Aus dem Desktop starten Sie aus dem Menü eines der Programme, die Terminal im Namen tragen. Bei MATE ist dies ANWENDUNG | SYSTEMWERKZEUGE | TERMINAL. Sie erhalten ein Fenster mit einer Shell. Da Sie davon beliebig viele Fenster öffnen können, lohnt es sich schon darum, eine grafische Oberfläche für einen Server zu installieren.
  • Per Fernwartung können Sie eine Shell auf dem zu wartenden Rechner starten. Dazu verwenden Sie den Befehl ssh, der in Kapitel 5 ausführlicher beschrieben wird.
  • Und dann gibt es noch die Computer, auf denen keine grafische Oberfläche installiert ist. Das ist bei Anwendermaschinen eher selten, aber bei dem einen oder anderen Server lohnt !es sich, keine grafische Oberfläche zu installieren. Man spart Hauptspeicher, Festplattenplatz und Rechenleistung. Und unter Linux kann man einen Computer bequem ohne grafische Oberfläche bedienen.

Tastenkombinationen

In einer Shell gibt es bestimmte Tastenkombinationen, die Sie kennen sollten:

  • +: beendet das aktuell laufende Programm.
  • +: stoppt die Ausgabe und blockiert scheinbar das Programm.
  • +: löst die Ausgabesperre von + wieder auf.
  • +: bewirkt eine Pausierung des aktiven Programms.

    Ist Ihnen das aus Versehen passiert, können Sie durch den Befehl fg den vorigen Zustand wieder herstellen. Näheres erfahren Sie in Kapitel 1 unter den Stichworten »kill« und »Signale«.

  • +: beendet eine Terminalsitzung, indem es das Ende des Datenstroms markiert.

Wenn nach der Ausführung eines Befehls vor Ihren Augen gerade eine riesige Menge an Zeilen vorbeigerauscht ist, die Sie gern noch einmal in Ruhe anschauen wollen, können Sie zurückblättern.

  • +: blättert in den bisherigen Ausgaben zurück
  • +: blättert in den bisherigen Ausgaben vorwärts

Befehlsrecycling

Sie können zuvor abgegebene Befehle zur Wiederverwendung in die Kommandozeile zurückholen. Dazu verwenden Sie die Pfeiltasten. Mit holen Sie Schritt für Schritt die letzten Befehle zurück. Mit können Sie in die andere Richtung blättern. Innerhalb eines Befehls können Sie und verwenden. Sie können die Korrekturtasten verwenden und Buchstaben einfügen.

Mit der Tastenkombination + können Sie sogar mit Stichwörtern in der Befehlsgeschichte suchen. Mit jedem Buchstaben, den Sie eingeben, wird der zuletzt eingegebene Befehl hervorgebracht, der noch auf das Muster passt. Die zuletzt eingegebenen Befehle können selbst nach zwischenzeitlichem Ausschalten des Computers wieder hervorgeholt werden, weil sie in der Datei .bash_history gespeichert werden.

Manpage als Bedienungsanleitung

Die Shell bietet zu fast jedem Befehl und zu den meisten Konfigurationsdateien eine Handbuchseite an, die über den Befehl man aufgerufen werden kann. Das ist auch bei Programmen üblich, die Sie nachträglich installieren.

Als Argument für man geben Sie den Befehl an, für den Sie Hilfe benötigen. Beispielsweise rufen Sie mit dem folgenden Befehl die Manpage für den Befehl ls auf:

$ man ls

Die Seite zeigt die Argumente und Optionen des Befehls. Falls Ihnen der Befehlsname nicht einfällt, können Sie nach einem Stichwort suchen, indem Sie -k angeben: Der folgende Befehl listet alle Programme auf, die etwas mit einem Verzeichnis zu tun haben.

$ man -k Verzeichnis

Wenn Sie alles über man erfahren wollen, können Sie natürlich man man aufrufen. Da die Manpages meist mehrseitig sind, helfen die folgenden Tastenkombinationen beim Lesen.

  • Sie können mit der Leertaste vorwärtsblättern.
  • Mit der Taste blättern Sie zurück.
  • Es funktionieren auch die Bild- und Cursortasten wie gewohnt.
  • Mit dem Schrägstrich können Sie die Suche nach einem Stichwort einleiten.
  • Die Taste führt dazu, dass die Manpage verlassen wird.

Befehlsempfänger Shell

Wenn Sie eine Terminalsitzung eröffnet haben, finden Sie an jedem Zeilenanfang einen sogenannten Prompt.

user@server ˜ $

Bei den meisten Linux-Versionen stehen darin standardmäßig der Benutzername, ein @, der Hostname und der aktuelle Pfad. Im Beispiel oben sehen Sie eine Tilde, die für das jeweilige Heimatverzeichnis des Benutzers steht.

Es folgt ein Dollarzeichen bei normalen Benutzern oder ein Doppelkreuz (#), falls Sie als root angemeldet sind. Daneben blinkt der Cursor. Dort geben Sie Ihre Kommandos ein und schließen sie mit ab.

Befehlsaufbau

Kommandos an die Shell haben die folgende Struktur:

  • Ein Kommando beginnt immer mit einem Befehl beziehungsweise mit einem Programmaufruf.
  • Es folgen Optionen, die mit einem Minuszeichen eingeleitet werden.
  • Dann kommen die Argumente. Das sind die Objekte, auf die der Befehl wirkt.

Optionen

Optionen verändern die Befehlsauswirkungen. Beispielsweise sorgt die Option -l beim Befehl ls dafür, dass mehr Details der Dateien angezeigt werden.

Wenn mehrere Optionen angegeben werden sollen, können sie zusammengefasst werden. Statt -a -u -x kann auch -aux geschrieben werden.

Klassischerweise bestehen Optionen nur aus einem Buchstaben hinter dem Minuszeichen. Das kommt der Tippfaulheit der meisten Informatiker sehr entgegen. Andererseits sind so kurze Optionen nicht gerade selbstdokumentierend.

Darum gibt es inzwischen Optionen, die aus kompletten Worten bestehen. Um sie von den klassischen Optionen zu unterscheiden, spendiert man ihnen zwei Minuszeichen. So kann man bei ls auch die Option --all statt -a verwenden.

Argumente

Argumente sind die Objekte, auf die ein Befehl wirkt. Meist sind das Dateien und so hilft die Shell geflissentlich mit der Autovervollständigung aus. Wenn Sie die ersten Buchstaben eines Arguments getippt haben, können Sie die Taste tippen und die Shell vervollständigt das Argument, soweit die Buchstaben es hergeben.

Wenn Sie beispielsweise die Dateien weihnachtsbaum und weihnachtsmann in einem Verzeichnis haben, reicht nach Eingabe des Buchstabens w ein Druck auf und es steht dort weihnachts, gefolgt vom Cursor. Ein weiterer führt nicht weiter, da es mehrere Möglichkeiten gibt. Wiederholen Sie noch einmal den Druck auf die -Taste, erscheinen die beiden möglichen Dateinamen. Geben Sie noch einen Buchstaben ein und schon wird nach dem nächsten Druck auf die Taste der richtige Dateiname verwendet.

Wildcards

Um mehrere Dateien anzusprechen, können Sie die entsprechenden Dateien von Leerzeichen getrennt aufzählen oder Sie können sogenannte Wildcards als Platzhalter verwenden.

Das Fragezeichen steht für genau einen Buchstaben. Ma?s passt also auf Mais oder Maus.

Der Stern steht für beliebig viele beliebige Zeichen. Sie könnten ihn oben auch statt des Fragezeichens einsetzen. Dann würde der Ausdruck allerdings auch auf das Wort Markenstatus passen.

In manchen Fällen ist es ganz wichtig zu wissen, dass die Auswertung der Wildcards von der Shell betrieben wird. Die Shell generiert aus den gefundenen Dateinamen eine Liste, die sie an der Stelle der Maske in die Kommandozeile einfügt. Dieses Vorgehen hat den Vorteil, dass die Anwendungen die Wildcards nicht selbst auswerten müssen und darum ihr Verhalten systemweit gleich ist.

Die Auswertung der Sonderzeichen verhindern

Wenn ein Programm aber einen Stern als Parameter erwartet, beispielsweise als Multiplikationszeichen, dann wäre es fatal, wenn die Shell stattdessen alle Dateinamen des Verzeichnisses liefert. In solchen Fällen muss das Sonderzeichen vor der Interpretation durch die Shell geschützt werden.

Bei einzelnen Zeichen verwenden Sie dazu einfach einen Backslash (\). Setzen Sie einen Backslash vor den Stern, wird die Shell ihn nicht interpretieren.

Dasselbe gilt für Leerzeichen. An sich trennen Leerzeichen zwei Dateinamen. Wenn aber der Name einer Datei ein Leerzeichen enthält, müssen Sie den Backslash vor das Leerzeichen stellen. Beispielsweise müssten Sie einen Film mit dem Titel Is was, Doc?.avi mit dem folgenden Befehl löschen:

$ rm Is\ was\,\ Doc\?.avi

Alternativ kann das Argument auch in Anführungszeichen ('') oder Hochkommata (') gesetzt werden. In diesem Fall interpretiert die Shell nicht die Sonderzeichen, sondern reicht sie direkt an das aufgerufene Programm weiter.

Der Unterschied zwischen Hochkomma und Anführungszeichen ist, dass Variablen in Anführungszeichen durch ihren Inhalt ersetzt werden, in Hochkommata nicht. Anders ausgedrückt erlauben Anführungszeichen der Shell mehr Zugriffe auf den Parameter als Hochkommata.

Datenströme

Linux betrachtet die Ausgabe von Programmen nicht als einzelne Zeichen, sondern als Datenströme, die man beispielsweise in Dateien umleiten oder als Eingabestrom in andere Programme führen kann.

Datenstrom in Dateien umleiten

Linux-Programme schieben ihre Ausgaben in einem Datenstrom in die Standardausgabe. Das Ausgabemedium ist im Normalzustand der Bildschirm. Die Shell kann mit einem Größerzeichen diese Standardausgabe in eine Datei umleiten. Der folgende Befehl leitet die Ausgabe des Befehls cat in die Datei umleitung.txt um.

$ cat /etc/passwd > umleitung.txt

Das Größerzeichen löscht den bisherigen Inhalt der Zieldatei. Wenn Sie die Ausgabe an den bisherigen Inhalt der Datei anhängen wollen, verwenden Sie zwei Größerzeichen.

$ cat /etc/passwd >> umleitung.txt

Umleitung der Eingabe

Mit dem Kleinerzeichen können Sie den Inhalt einer Datei einem Programm als Eingabe zuführen. Man kann auch beides kombinieren, wie der folgende Sortierungsbefehl zeigt.

sort < eingabedatei > ausgabedatei

Auf diese Weise wird die Datei eingabedatei als Eingabe für den Sortierbefehl verwendet und die Ergebnisse werden in der Datei ausgabedatei abgelegt.

Ausgabe als Eingabe durchleiten

Statt die Ausgabe in eine Datei umzuleiten, können Sie eine Ausgabe an einen Prozess weitergeben, der diese Daten als Eingabe übernimmt. Ein typisches Beispiel ist das Weiterleiten größerer Textinhalte an das Programm more, um in der Ausgabe blättern zu können. Diese Weiterleitung erfolgt mit dem Pipe-Symbol, dem senkrechten Strich.

$ cat /etc/passwd | more

Sobald das Terminal mit dem Inhalt gefüllt ist, stoppt more die Ausgabe und wartet auf eine Taste.

  • Die Leertaste blättert seitenweise.
  • Die Taste blättert zeilenweise.
  • Mit der Taste können Sie die Ausgabe abbrechen.

Fehlerausgabekanal

Nicht nur die Standardausgabe landet normalerweise auf dem Bildschirm, sondern auch sämtliche Fehlermeldungen. Allerdings wird dazu nicht der Standardausgabekanal, sondern ein spezieller Fehlerkanal verwendet. Der Unterschied ist nicht erkennbar, solange beides auf den Bildschirm geht.

Aber man kann die Kanäle trennen. Wird die Standardausgabe in eine Datei umgeleitet, erscheinen die Fehler immer noch auf dem Bildschirm. Will man aber explizit die Fehler in einer Datei sammeln, stellt man vor das Größerzeichen eine 2 und sorgt so dafür, dass dieser zweite Kanal in eine eigene Datei umgeleitet wird:

$ tudochwas > ausgabedatei 2> fehlerdatei

Sie können auch den Ausgabe- und den Fehlerkanal gemeinsam in eine Datei laufen lassen. Dazu setzen Sie ein Und-Zeichen direkt hinter das Größerzeichen:

$ tudochwas >& ausgabeundfehlerdatei

Löschen durch Umleiten

Wenn Sie ein Größerzeichen zur Umleitung verwenden, wird die Zieldatei zuerst einmal gelöscht. Tatsächlich können Sie diesen Effekt benutzen, um eine Datei auf 0 zu setzen, also ihren Inhalt zu löschen. Dazu leiten Sie einfach nichts auf eine Datei um:

$ > gleichleer

Manchmal entstehen Ausgaben, die nur stören. Um sie loszuwerden, können Sie sie in die für solche Zwecke vorgesehene Datei /dev/null umleiten. Alle Daten, die auf diese Pseudodatei umgeleitet werden, verschwinden auf Nimmerwiedersehen.

Datenabzweigung: tee

Manchmal gibt es für Daten, die von einem zum anderen Programm über eine Pipe geleitet werden, noch weitere Interessenten. Dafür gibt es das Programm tee, das wie ein T-Stück zwischen die Pipe geschraubt wird. Es zweigt eine Kopie des Datenstroms in eine Datei ab. Welche Datei das ist, geben Sie als Argument an. Im folgenden Beispiel heißt das Sammelbecken ausgabedatei.

$ ls -l | tee ausgabedatei | more

Quoting: Befehle verschachteln

In manchen Fällen benötigen Sie aber die Ergebnisse eines Programms als Bestandteil eines Befehlsaufrufs.

So möchte man vielleicht alle HTML-Dateien editieren, in denen ein Link auf andere Webseiten behandelt wird. Eine solche Referenz wird in HTML mit der Anweisung href gekennzeichnet. Der Befehl grep wird in Kapitel 1 behandelt und sucht Begriffe in Dateien und zeigt alle Zeilen an, in denen der Begriff vorkommt. Die Option -i passt gut, weil HTML die Anweisungen in Groß- und Kleinschreibung akzeptiert. Setzt man diesem allerdings noch die Option -l hinzu, zeigt grep die Dateinamen an, in denen der Suchbegriff zu finden ist.

$ grep -li href *.htm

Diese erzeugte Liste der Dateien möchte man gern als Argument für einen Editor, beispielsweise vi, verwenden. Um die Liste der Dateien als Argument eines Aufrufs nutzen zu können, wird der grep-Befehl per Quoting übernommen.

Für das Quoting werden Backquotes verwendet, von Experten auch Rückwärtsdüdel genannt. Es handelt sich um die Hochkommata, die eine leichte Neigung rückwärts haben, also von links oben nach rechts unten. Auf der deutschen Tastatur findet man die Taste rechts neben dem , wenn man gleichzeitig die Taste tippt.

Neben der akrobatischen Erzeugung ist das Rückwärtsdüdel auch auf dem Bildschirm oder in Büchern nur schwer von einem Hochkomma zu unterscheiden, wie das folgende Beispiel zeigt.

$ vi `grep -li href *.htm`

Darum verwende ich gern die alternative Schreibweise. Sie besteht darin, dass man den Befehl einklammert und ein Dollarzeichen vor die Klammer setzt. Das ist verwechslungsfrei zu lesen und auch nicht komplizierter zu tippen.

$ vi $(grep -li href *.htm)

Wie auch immer Sie das Quoting erzeugen, es führt dazu, dass der Inhalt erst ausgeführt und das Ergebnis in das Kommando eingefügt wird.

Anweisungen gruppieren

Wenn Sie mehrere Anweisungen nacheinander ausführen wollen, dann können Sie diese nacheinander in eine Zeile schreiben und sie durch ein Semikolon trennen. Das Semikolon hat die gleiche Wirkung, als hätten Sie zwischen den beiden Kommandos die Taste gedrückt. Sie können dies beispielsweise einsetzen, wenn Sie ein länger laufendes Programm aufrufen, aber wissen wollen, wann es fertig ist, ohne die ganze Zeit vor dem Monitor sitzen zu müssen.

$ langlaufendesprogramm ; date

Erst wenn das Programm langlaufendesprogramm fertig ist, wird der Befehl date gestartet, der Datum und Uhrzeit ausgibt.

Abhängige Anweisungen

Zwei Kommandos können nicht nur einfach getrennt werden. Es ist auch möglich, ein Kommando in Abhängigkeit davon auszuführen, ob ein anderes Kommando Erfolg hatte.

Wird zwischen zwei Anweisungen ein doppeltes Ampersand, also kaufmännisches Und, gesetzt, wird die zweite Anweisung nur ausgeführt, wenn die erste keinen Fehler zurückgegeben hat. So können Sie beispielsweise ein Dokument mit generieren und dieses nur dann in PostScript konvertieren, wenn der erste Lauf erfolgreich war:

$ latex dokument.tex && dvips dokument

Andererseits gibt es auch den Fall, dass ein Kommando nur dann aufgerufen werden soll, wenn der vorherige Befehl erfolglos war. Dann fügen Sie zwischen die Anweisungen einen doppelten senkrechten Strich ein. So können Sie beispielsweise eine Fehlermeldung ausgeben, wenn der Übersetzungslauf unbefriedigend war:

$ latex dokument.tex || echo “Schlimmer Fehler”