2 Einführung in die Shell

Die Shell ist der Kommandointerpreter von UNIX. Es haben sich drei Typen entwickelt:

  • Bourne Shell (die erste Shell, angelehnt am ALGOL68), sh
  • C-Shell (angelehnt an C), csh
  • Korn Shell (das "Beste" aus Bourne- und C-Shell), ksh
Aus diesen sind weitere Shells entwickelt worden, z. B. die Bourne again shell, bash, die ähnliche Funktionen hat wie die ksh oder die tcsh als Abkömmling der csh.

2.1 Aufgaben der Shell

  • Kommandozeile vom Terminal annehmen, das Kommando entschlüsseln und in seine Komponenten (Kommandoname, Optionen, Parameter) aufteilen
  • Gewünschtes Programm suchen und starten. Der Suchweg wird durch eine Shellvariable PATH vorgegeben.
  • Steuerung der Ein- und Ausgabe des Terminals. UNIX ist als Dialogsystem konzipiert und war ursprünglich für den Betrieb mit Fernschreibern (Teletype) und Datensichtgerät konzipiert. Diese sogenannten "Terminals" findet man heute noch in den logischen Terminals, z. B.:
    • den Konsolen, die dem Bildschirm und der Tastatur des PCs zugeordnet sind,
    • den Pseudo-Terminals, die einer Telnet-Verbindung zugeordnet werden oder
    • den X-Terminal-Fenstern auf der grafischen Benutzeroberfläche.
    Daher gibt es drei Standarddateien, die dem aktuellen Terminal zugeordnet sind:
    • Standardeingabe (Tastatur, stdin)
    • Standardausgabe (Bildschirm, stdout)
    • Standard-Fehlerausgabe (Bildschirm, stderr)
    Die Shell kann angewiesen werden, die Ein- und Ausgaben umzuleiten.
  • Ersetzung von Sonderzeichen und Befehlssubstitution. Kommandoeingaben können durch Sonderzeichen erweitert und der Kommandostring kann selbst durch die Shell expandiert werden.
  • Ablaufsteuerung. Die Shell beherrscht viele Strukturen, wie man sie von Programmiersprachen her kennt (Test, bedingte Anweisung, Schleifen, Variablen, Rechenanweisungen).
  • Erzeugen von Kind- und Hintergrundprozessen.
Es gibt weiterhin die Möglichkeit, Programme "im Hintergrund" zu starten und am Bildschirm weiterzuarbeiten, während das Programm läuft. Sobald die Shell bereit ist, Kommandoeingaben anzunehmen, meldet sie sich mit einem Bereitschaftszeichen (Prompt). Im einfachsten Fall ist dies ein "$"-Zeichen als normales Prompt, dem "#" als Prompt für Superuser und dem ">"-Prompt, wenn noch weitere Eingaben erwartet werden. Wie vieles in der Shell, kann der Prompt beliebig modifiziert werden.

Anmerkungen:

  1. In diesem Kapitel geht es um grundlegende Eingenschaften der Shell, später wird das Thema noch vertieft.
  2. Die Shell ist ein ganz normales Programm, das von der Standardeingabe (Tastatur) liest und auf die Standardausgabe (Bildschirm) ausgibt. Wenn das Dateiende erreicht wird (End Of File, EOF), z. B. durch Eingabe von CTRL-D, terminiert sie. Ist es die Login-Shell, erfolgt ein Logoff des Benutzers.
  3. Die Shell kann wie ein Programm als Subshell aufgerufen werden (Schachtelung). Dies wird beispielsweise benötigt, wenn man Shell-Programme (shell skripts) testen will.
  4. Suchpfade für Kommandos: Es gibt zwei Möglichkeiten, den Pfad für ein Kommando festzulegen:
    1. Direkt als absoluter oder relativer Pfadname
    2. Indirekt über den Pfad, der in der Shell-Variablen PATH gespeichert ist.

Kommandobeschreibung

In der Literatur (auch beim Kommando "man") werden die Kommandos in Kurzform beschrieben. Dabei werden Werte, die optional sind, in eckige Klammern gesetzt. Die (meist einbuchstabigen) Optionen werden als Kette aufgelistet, z.B. [-aeGhlz]. Das bedeutet nichts anderes, als daß eine beliebige Kombination dieser Optionen möglich ist (ob sie sinnvoll ist, wird hier nicht berücksichtigt).

UNIX-Benutzer sind "mündig"! Was heißt das? Wenn Sie ein Kommando eingeben, das die gesamte Platte löscht, fragt das Programm nicht noch einmal nach, ob Sie das auch wirklich wollen, sondern löscht die Platte sofort.

Beim Testen von Shell-Programmen hilft das Kommando

echo [Argumente]

Dieses Kommando gibt die Argumente auf dem Bildschirm aus. Für den Einsteiger ist das Kommando wichtig, weil er so die Kommandobearbeitung der Shell recht gut verfolgen und studieren kann (Einstreuen von echo-Kommandos in die Befehlsfolge).

Bearbeitung der Kommandozeile durch die Shell

Ein Kommando wird erst ausgeführt, wenn der Benutzer am Ende der Kommandozeile die RETURN-Taste drückt. Eine genauere Kenntniss des dann vonstatten gehenden Ablaufs erlaubt es, zu verstehen, warum etwas nicht so klappt, wie man es sich vorgestellt hat. Daher sollen diese Schritte hier kurz beschrieben werden. (Anmerkung: Einige der Kommandotrenner, `...`, Jokerzeichen und Variablen werden erst später behandelt.):
  1. Die Shell liest bis zum ersten Kommandotrenner (& && || ; > <) und stellt fest, ob Variablenzuweisungen erfolgen sollen oder die Ein-Ausgabe umgelenkt werden muß.
  2. Die Shell zelegt die Kommandozeile in einzelne Argumente. Sie trennt die einzelnen Argumente durch eines der Zeichen, die in der Shell-Variablen IFS (Internal Field Separator) stehen, normalerweise Leerzeichen, Tabs und Newline-Zeichen.
  3. Variablenreferenzen, die in der Kommandozeile stehen, werden durch ihre Werte ersetzt.
  4. Kommandos, die in `...` oder bei der bash in $(...) stehen, werden ausgeführt und durch ihre Ausgabe ersetzt.
  5. stdin, stdout und stderr werden auf ihre "Zieldateien" umgelenkt.
  6. Falls in der Kommandozeile noch Zuweisungen an Variablen stehen, werden diese ausgeführt.
  7. Die Shell sucht nach Jokerzeichen und und ersetzt diese durch passende Dateinamen.
  8. Die Shell führt das Kommando aus.

2.2 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:

&0Standardeingabe
&1Standardausgabe
&2Standard-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 <a <b >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<Datei-1 4<Datei-2 5<Datei-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. Boume-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 <datei
    
    verbindet beispielsweise die Standardeingabe mit einer Datei,
    exec <&3
    
    stellt die alte Verbindung wieder her. Der Ordnung halber schließt man mit exec 3<& den zusätzlichen Eingabekanal, wenn man ihn nicht mehr braucht. Analog dazu schließt der Operator x>&- einen Ausgabekanal.

2.3 Pipes

Eine Pipe verbindet zwei Kommandos über einen temporären Puffer, d. h. die Ausgabe vom ersten Programm wird als Eingabe vom zweiten Programm verwendet. Alles, was das erste Programm in den Puffer schreibt, wird in der gleichen Reihenfolge vom zweiten Programm gelesen. Pufferung und Synchronisation werden vom Betriebssystem vorgenommen. Der Ablauf beider Prozesse kann verschränkt erfolgen. In einer Kommandofolge können mehrere Pipes vorkommen. Der Pipe-Mechanismus wird durch das Zeichen "|" (senkrechter Strich) aktiviert:

Kommando 1 | Kommando 2

Beispiel: Ausgabe der Dateien eines Verzeichnisses mit der Möglichkeit, zu blättern:

Natürlich können auch mehrere Kommandos hintereinander durch Pipes verbunden werden:

Kommando 1 | Kommando 2 | Kommando 3 | Kommando 4 | ...

Pipelines haben Vorrang vor anderen Formen der Ein- und Ausgabeumleitung. Bevor die Shell mit der Ausführung der Einzelbefehle und der dazugehörenden Umleitungen beginnt, baut sie die gesamte Pipeline zusammen: Sie erzeugt für jeden Abschnitt einen neuen Prozeß und verbindet die Standardausgabe jedes Prozesses mit der Standardeingabe des Nächsten. Will der Anwender die Fehlerausgabe eines Programms ebenfalls durch die Pipeline schicken, kann er in Bourne-Shell-Skripten

foo 2>&1 | bar
schreiben. Da die Shell die Pipeline-Verbindung zuerst herstellt, landen die Fehlermeldungen vom Programm foo auf der Standardeingabe von bar.

Kommandofolgen, die durch Pipes verbunden sind, werden auch als "Filter" bezeichnet. Einige nützliche Filter sind in jedem UNIX-System verfügbar. Zum Beispiel:

head [-n] [datei(en)]
Ausgabe der ersten n Zeilen aus den angegebenen Dateien. Voreinstellung ist 10 Zeilen. Wird keine Datei angegeben, liest head von der Standardeingabe.

tail [-/+n] [bc[f|r]] [datei]
Ausgabe der letzten n Zeilen einer Datei. Voreinstellung für n ist 10. Wird keine Datei angegeben, liest tail von der Standardeingabe.

Optionen
+nab der n. Zeile ausgeben
-ndie letzten n Zeilen ausgeben Wird hinter die Zahl n ein 'b' gesetzt (z. B. -15b), werden nicht n Zeilen, sondern n Blöcke ausgegeben. Wird hinter die Zahl n ein 'c' gesetzt (z. B. -200c), werden nicht n Zeilen, sondern n Zeichen (characters) ausgegeben.
-r Zeilen in umgekehrter Reihenfolge ausgeben (letzte zuerst). Geht nicht bei GNU-tail - stattdessen kann man das Programm toc verwenden.
-f tail am Dateiende nicht beenden, sondern auf weitere Zeilen warten. (Ende des Kommandos mit der CTRL-C-Taste). Damit kann man z. B. Logfiles beobachten, die ständig wachsen.

tee [-i] [-a] [datei]
Pipe mit T-Stück: Kopiert von stdin nach stdout und schreibt die Daten gleichzeitig in die angegebene Datei.

Optionen
-iIgnorieren von Interrupts (Unterbrechungs-Taste)
-aAnhängen der Info an die angegebene Datei (Voreinstellung: Überschreiben der Datei)

wc [-lwc] [Datei(en)]
Dieses Kommando zählt Zeilen, Worte oder Zeichen in einer Datei. Wird kein Dateiname angegeben, liest wc von der Standardeingabe. Normalerweise zählt man damit in Skripten irgendwelche Ergebnisse. Optionen:

-l Zähle Zeilen
-wZähle Worte
-cZähle Zeichen

Weitere Filter sind more, less, tr, ....

2.4 Metazeichen zur Expansion von Dateinamen

Damit man beim Angeben von z. B. Dateinamen nicht alle Namen eintippen muß, sondern die Dateien auch alle oder nach bestimmten Kriterien auswählen kann, gibt es Metazeichen (Jokerzeichen, Wildcards). Im Gegensatz zu anderen Systemen (z. B. MS-DOS) werden diese von der Shell ersetzt. Dies ist eine ganz wichtige Tatsache, die zur Folge hat, daß nahezu jedes UNIX-Kommando als Dateiangabe immer eine (im Rahmen der BS-Parameter) beliebige Menge von Dateien als Parameter haben kann. Im Programm sind daher auch keine Systemaufrufe nötig, die auf die Verzeichnisinformation zugreifen; es wird lediglich eine Schleife benötigt, welche die einzelnen Dateien nacheinander bearbeitet. Metazeichen sind Zeichen mit erweiterter Bedeutung. Die Shell ersetzt die Metazeichen durch alle Dateinamen des aktuellen Verzeichnisses, die auf das Muster passen. Dabei können die Metazeichen beliebig oft an beliebiger Stelle im Dateinamen stehen (z. B.: *abc*def*). Es gibt folgende Metazeichen:

* Der Stern steht für eine beliebige Zeichenfolge - oder für überhaupt kein Zeichen. Dazu ein Beispiel:
"ab*" steht für alle Dateinamen, die mit "ab" anfangen, auch für "ab" selbst ("ab", "abc", "abcd", "abxyz", usw.).
? Das Fragezeichen steht für genau ein beliebiges Zeichen. Zum Beispiel:
"?bc" steht für alle Dateinamen mit 3 Zeichen, die auf "bc" enden ("abc", "bbc", "1bc", "vbc", "xbc", usw.), nicht jedoch für "bc".
[ ] Die eckige Klammer wird ersetzt durch eines der in der Klammer stehenden Zeichen. Auch ein Bereich ist möglich, z. B. [a-k] = [abcdefghijk]. Beispiel: "a[bcd]" wird ersetzt durch "ab", "ac" und "ad". Soll das Minuszeichen selbst in die Zeichenmenge aufgenommen werden, muß es an erster Stelle stehen (gleich nach der öffnenden Klammer).
[! ] Die eckige Klammer mit Ausrufezeichen wird ersetzt durch eines der nicht in der Klammer stehenden Zeichen, zum Beispiel: "[!abc]" wird ersetzt durch ein beliebiges Zeichen außer a, b oder c. Soll das Ausrufezeichen selbst in die Zeichenmenge aufgenommen werden, muß es an letzter Stelle stehen.
\ Der Backslash hebt den Ersetzungsmechanismus für das folgende Zeichen auf. Beispiel: "ab\?cd" wird zu "ab?cd" - das Fragezeichen wird übernommen. Wichtig: Bei der Umleitung von Ein- und Ausgabe werden Metazeichen in den Dateinamen hinter dem Umleitungszeichen nicht ersetzt.

Beispiele für die Anwendung:
ls -l a* listet alle Dateien, die mit "a" anfangen

ls test? listet alle Dateien die mit "test" anfangen und 5 Zeichen lang sind ("test1", "test2", "testa")

ls /dev/tty1[1-9] listet alle Terminalbezeichnungen mit einer 1 in der Zehnerstelle ("tty11", "tty12", ... , "tty19")

Lebenswichtig:
Der * ist ein gefährliches Zeichen, Tippfehler könne zum Fiasko führen, wenn aus Versehen ein Leerzeichen zuviel getippt wird.
rm a* löscht beispielsweise alle Dateien, die mit "a" anfangen.
rm a * löscht dagegen erst die Datei "a" und dann alle Dateien im Verzeichnis.

Anmerkungen:

  • Der Punkt am Anfang von Dateinamen stellt eine Ausnahme dar, er muß explizit angegeben werden (wegen der Verzeichnisreferenzen "." bzw. ".." und der Tatsache, daß Dateien, die mit einem Punkt beginnen, normalerweise nicht angezeigt werden).
  • Der "\"am Zeilenende unterdrückt auch das Return-Zeichen - das Kommando kann in der folgenden Zeile fortgesetzt werden (es erscheint dann der Prompt ">" anstelle von "$").

2.5 String-Ersetzungen (Quoting)

Um bestimmte Sonderzeichen (z. B. *, ?, [ ], Leerzeichen, Punkt) zu übergeben, ohne daß sie von der Shell durch Dateinamen ersetzt werden, werden Anführungszeichen verwendet, die auch ineinander geschachtelt werden können. Dabei haben die drei verschiedenen Anführungszeichen Doublequote ("), Quote (') und Backquote (`) unterschiedliche Bedeutung:

" " Keine Ersetzung der Metazeichen * ? [ ], jedoch Ersetzung von Shellvariablen (siehe unten) und Ersetzung durch die Ergebnisse von Kommandos (Backquote). Auch \ funktioniert weiterhin. Dazu ein Beispiel:
echo Der * wird hier durch alle Dateinamen ersetzt
echo "Der * wird hier nicht ersetzt"
' ' Das einfache Anführungszeichen unterdrückt jede Substitution. Zum Beispiel:
echo 'Weder * noch `pwd` werden ersetzt'
` ` Zwischen Backquote (Accent Grave) gesetzte Kommandos werden ausgeführt und das Ergebnis wird dann als Parameter übergeben (d. h. die Ausgabe des Kommandos landet als Parameter in der Kommandozeile). Dabei werden Zeilenwechsel zu Leerzeichen. Braucht dieses Kommando Parameter, tritt die normale Parameterersetzung in Kraft. Zum Beispiel:
echo "Aktuelles Verzeichnis: `pwd`"

Weil die verschiedenen Quotes manchmal schwer zu unterscheiden sind, wurde bei der bash eine weitere Möglichkeit eingeführt. Statt in Backquotes wird die Kommandofolge in $( ... ) eingeschlossen., z. B.:
echo "Aktuelles Verzeichnis: $(pwd)"

2.6 Bash - Die Linux-Shell

Die Bash (Bourne Again SHell) ist vollständig kompatibel zu der originalen Bourne-Shell aber sie hat etliche Erweiterungen erfahren. Sie ist bei fast allen Linux-Systemen die Standard-Shell.

Beim Start liest die Bash eine Reihe von Konfigurationsdateien ein, interpretiert deren Inhalt und ?nimmt bestimmte Einstellungen. Was dabei genau geschieht, h?t von mehreren Faktoren ab.

Ist die Bash als Login-Shell eingestellt, wird zun?st die Login-Konfigurationsdatei .bash_profile im Home-Verzeichnis des Anwenders gesucht. Ist sie vorhanden, f? die Bash die darin enthaltenen Befehle aus. Fehlt diese Datei, sucht die Bash im selben Verzeichnis nach einer Konfigurationsdatei mit dem Namen .bash_login. Fehlt auch diese, wird versucht, die systemweit g?ge Konfigurationsdatei /etc/profile einzulesen und auszuwerten. Als letzte M?chkeit versucht die Login-Bash, die Datei .profile im Home-Verzeichnis des Anwenders auszuf?n.

Als interaktive (Sub) Shell liest die Bash ihre Konfiguration aus der Datei .bashrc (im Home-Verzeichnis des Anwenders). Eine interaktive Bash verwendet f?en Befehlszeileneditor zus?lich die Einstellungen aus der Konfigurationsdatei .inputrc. Diese Datei wird zun?st im Home-Verzeichnis des Anwenders gesucht, ist sie dort nicht vorhanden, wird im Konfigurationsverzeichnis /etc/ nach der Datei inputrc gesucht.

Eine nicht interaktive (Sub-) Shell, wie sie zum Start von Skripten verwendet wird, liest keine Konfigurationsdateien ein, sofern dies nicht explizit gefordert wird.

Einige Versionen der Bash (z. B. die von SuSE Linux verwendete) suchen als interaktive Shell zun?st im Konfigurationsverzeichnis /etc/ nach systemweit g?gen Einstellungen in der Datei bash.bashrc. Diese ist aber normalerweise nicht vorhanden bzw. leer. Anschlie?nd und unabh?ig davon, ob diese Datei gefunden wurde, wird die pers?che Konfigurationsdatei .bashrc im Home-Verzeichnis des Anwenders eingelesen.

Damit bei einer Login-Shell auch Funktionen einer interaktiven Shell zur Verf?g stehen, wird am Ende der Login-Konfigurationsdatei oft auch die pers?che Konfigurationsdatei im Home-Verzeichnis des Anwenders eingelesen.

SuSE Linux l?die Konfiguration der Bash in folgender Weise: Die systemweite Konfiguration erfolgt in der Datei /etc/profile, an deren Ende weitere Konfigurationsdateien ausgef? werden:

  • /etc/SuSEconfig/profile
  • alle Skripte in /etc/profile.d
  • /etc/profile.local

Auch beim Verlassen der Shell k?n von der Bash noch automatisch Befehle ausgef? werden. Die Bash f? beim Eintreffen eines exit-Befehls die Datei .bash_logout im Home-Verzeichnis des Anwenders aus. Vorsicht: Nicht alle Versionen der Bash werten diese Datei korrekt aus.

Die Ausführung der Dateien läßt sich über zwei Kommandozeilen-Parameter steuern. Mit dem Parameter -noprofile veranlassen Sie, daß die Bash keine der oben genannten Startdateien ausführt, mit -norc erreichen Sie, daß die persönliche Konfigurationsdatei -/.bashrc ignoriert wird.

Der Prompt

Die Bash gibt einen Eingabeprompt aus, häufig in der Form Username:Pfad> . Der Prompt ist über die Umgebungsvariable PS1 konfigurierbar. Ein Prompt in der o. a. Form resultiert aus der Einstellung PS1=\u:\w\$ .
Um andere Einstellungen auszuprobieren, müssen Sie die Variable neu belegen. Innerhalb dieser neuen Einstellungen können Sie einige spezielle Codes verwenden:

Codes f?ie Konstruktion des Prompts
CodeWirkung
\a Das Bell-Zeichen, wie es durch die Tastenkombination [Ctrl][g] erzeugt wird
\d das aktuelle Datum im Format Thu Jan 18
\e das Escape-Zeichen
\H der gesamte (Host) -Name
\h der Rechner (Host) -Name bis zum ersten Punkt
\n ein Newline (LineFeed) -Zeichen
\r ein Return (Carriage Return) -Zeichen
\s der Programmname der Bash, also bash
\t die aktuelle Systemzeit im 24-Stundenformat HH:MM:SS
\T die aktuelle Systemzeit im 12-Stundenformat HH:MM:SS
\@ die aktuelle Systemzeit im 12-Stundenformat mit am/pm (01:39am)
\u der Username
\v die Version der ausgef?en Bash (2.03)
\V Das Release der Bash, bestehend aus der Versionsnummer und dem Patchlevel (2.03.1)
\w das aktuelle Arbeitsverzeichnis in ausf?icher Darstellung, beispielsweise ~/LinuxMagazin/bash/teil6
\W der letzte Teil des aktuellen Verzeichnisses, etwa teil6
\! die (History-) Nummer der aktuellen Befehlszeile
\# die Nummer der Befehlszeile in der aktuellen Bash-Sitzung
\$ mit diesem Schl?n wird der Rootaccount gekennzeichnet. Wenn die effektive UID gleich Null ist, stellt die Bash das Hashmark dar, sonst ein Dollar-Zeichen
\NNN Jedes beliebige ASCII-Zeichen kann durch Eingabe des oktalen Codes nach einem Backslash erzeugt werden
\\ der Backslash selbst wird durch zwei Backslash-Zeichen erzeugt
\[ eine Folge von Steuerzeichen wird so eingeleitet
\] die Folge von Steuerzeichen wird so beendet

Edieren der Kommandozeile

Die Hauptaufgabe einer Shell ist die Entgegennahme und Ausführung von Kommandos. Zum Bearbeiten der aktuellen Kommandozeile stehen sowohl Emacs- als auch vi-kompatible Editiermodi zur Verfügung - voreingestellt ist der Emacs-Modus. Wenn Sie lieber im vi-Modus arbeiten, stellen Sie ihn durch den Befehl set -o vi ein, zurück in den Emacs-Modus geht's mit set -o emcas. Im Emacs-Modus gibt es unter anderem folgende Edierfunktionen:
  • [Cursor links] beziehungsweise [Cursor rechts] bewegen den Cursor in der Kommandozeile
  • [Esc], [F] springt bis zum nächsten Wortende
  • [Esc], [B] springt bis zum vorigen Wortanfang
  • [Strg]+[E] springt zum Zeilenende
  • [Strg]+[A] springt zum Zeilenanfang
  • [Strg]+[K] löscht den Text ab der Cursorposition bis zum Ende der Zeile
  • [Strg]+[Y] fügt den zuletzt gelöschten Text nach der Cursorposition ein
  • [Tab] ergänzt ein Eingabefragment zum passenden Dateinamen. Ist die Ergänzung nicht eindeutig möglich, ertönt ein Signalton und Sie erhalten mit der Kombination
  • [Tab], [Tab] eine Liste der in Frage kommenden Dateinamen

Abhängig von der eingesetzten Terminalemulation können Sie Kombinationen mit der [Esc]-Taste oft auch mit der [Alt]-Taste nachgebilden. Statt also nacheinander [Esc] und [F] zu drücken, funktioniert meist auch die Kombination [Alt]+[F].

History-Mechanismus

In der Bash können Sie nicht nur die aktuelle Kommandozeile editieren, sie merkt sich auch alle einmal eingegebenen Befehle in einer Datei, der Kommandozeilen-History. Auch diese Datei befindet sich im Home-Directory des Benutzers und heißt .bash_history. Mit den Cursortasten auf/ab kann man in dieser Liste blättern. Darüber hinaus stehen folgende History-Befehle zur Verfügung:
  • [Strg]+[R] sucht nach dem letzten Kommando anhand der Anfangsbuchstaben
  • [Esc] oder "Cursor links" springt an den Anfang der History-Liste
  • [Esc] oder "Cursor rechts" springt ans Ende der History-Liste

Die Anzahl der Befehlszeilen wird mit der Variablen HISTSIZE eingestellt. Wächst die History darüber hinaus, verwirft die Bash die ältesten Zeilen.

Wichtige interne Kommandos

  • alias weist einem Befehl oder einer Befehlsfolge einen neuen Namen zu. Beispiele für MS-DOS-Umsteiger sind:
    alias dir='ls -l'
    alias cd..='cd ..'
    alias md='mkdir'
    alias rd='rmdir'
    alias del='rm -i'
    
    Ohne Parameter gibt dieser Befehl eine Liste der aktuell definierten Aliasnamen aus. Zum Löschen eines Alias-Eintrags verwendet man den Befehl unalias Name.

  • fg, bg und jobs sind Befehle für die interne Jobkontrolle der Bash. Ein laufendes Programm kann mit [Strg]+[Z] in den Hintergrund verschoben werden; dort wird es zunächst angehalten ("suspend"). Das Kommando jobs gibt eine Liste aller derzeit im Hintergrund schlafenden Programme aus. Dabei wird für jedes Programm die interne Jobnummer angegeben. Es ist wichtig anzumerken, daß die vergebene Jobnummer in keinem Zusammenhang zu der - etwa von ps - angezeigten Prozeßnummer steht. Mit fg Jobnummer holen Sie diese Task wieder in den Vordergrund. Soll ein angehaltenes Kommando dagegen im Hintergrund weiterlaufen, verwendet man den Befehl bg Jobnummer.

  • dirs, pushd, popd verwalten den Stapel der internen Verzeichnisse. Mit pushd Verzeichnis wird das angegebene Verzeichnis auf dem Stapel abgelegt. Mit popd gelangen Sie anschließend zum zuletzt abgelegten Verzeichnis zurück. Den aktuellen Stapelinhalt zeigt der Befehl dirs an.

  • echo wurde ebenfalls erweitert. Soll der Zeilenumbruch am Ende der Ausgabe unterdrückt werden, verwendet man den Parameter -n. Wer die von der C-Funktion printf bekannten Ausgabesteuerzeichen verwenden will, gibt den Parameter -e an.

  • hash (ohne Parameter) zeigt die Liste der gemerkten Pfade zu den Programmen an. Um die Zugriffe auf Programme zu beschleunigen, verwaltet die Bash einen internen Cache der Pfade auf bereits gestartete Programme. Wird ein Programm erneut gestartet, kann die zeitaufwendige Suche entlang des Pfades entfallen. Bei der Gelegenheit wird auch gleich angezeigt, wie oft das Programm gestartet wurde. Wer am Abend wissen will, womit er sich den ganzen Tag über beschäftigt hat, kann mit diesem Kommando zumindest Hinweise bekommen (oder er wirft einen Blick auf die .bash_history.
    hash -r verwirft alle gespeicherten Pfade.

  • help ist die Hilfefunktion der Bash. Ohne Parameter aufgerufen, listet sie alle eingebauten Befehle auf. Mit einem Parameter wird ein Hilfetext über den angegebenen Befehl ausgeben.

  • logout führt das Skript .bash-logout aus und beendet die Login-Shell.

Mittels set einstellbare Optionen der Bash

Option Name Funktion
-a allexport neu definierte oder ver?erte Variablen werden automatisch exportiert
-b notify bewirkt, dass Meldungen von Hintergrundjobs sofort ausgegeben werden (voreingestellt wartet die Bash bis zur Ausgabe des n?sten Prompts)
-B braceexpand Klammerexpandierungen erlauben (entspricht der Voreinstellung)
-C noclubber Setzen dieser Option verhindert, dass bestehende Dateien durch Ausgabeumleitungen (Redirections) zerst?werden
-e errexit In diesem Modus beendet sich die Shell immer dann automatisch, wenn ein Befehl einen Fehlercode erzeugte
-f noglob Deaktiviert die Komplettierungsfunktion f?ateinamen
-h hashall Deaktiviert das Speichern der Pfade bereits einmal ausgef?er externer Befehle; ein Abschalten bewirkt l?ere Ausf?ngszeiten bei Skripten
-H histexpand Erlaubt erweiterte Ersetzungen aus dem Historybuffer (voreingestellt: on)
-k keyword Zuweisungen werden in das Environment des Befehls ?nommen
-m monitor Aktiviert die Job-Kontrollfunktionen (Voreinstellung: on bei interaktiven Shells)
-n noexec Verhindert die Ausf?ng von Befehlen; die Syntax wird aber ?pr?und gegebenenfalls Fehlermeldungen erzeugt (deaktiviert bei interaktiven Shells)
-o Option setzt die im Argument ?gebene Option, siehe das Beispiel oben
-p privileged Aktiviert den privilegierten Modus
-P physical Unterdr? die Darstellung von symbolischen Links, statt dessen wird das physikalische Verzeichnis verwendet
-t onecmd Die Shell terminiert nach dem Ausf?n des ersten Befehls
-u nounset Bewirkt, dass ungesetzt Variablen Fehlermeldungen erzeugen; ohne diese Option wird ihnen ein leerer Inhalt zugewiesen
-v verbose Befehlszeilen werden angezeigt, bevor sie ausgef? werden
-x xtrace Alle Befehlszeilen werden mit expandierten Argumenten angezeigt, bevor sie ausgef? werden

Mit der Einf?ng der Bash-Version 2.0 gibt es viele neue Konfigurations-Features. Sie werden durch den "erweiterten Konfigurationsbefehl" shopt gesetzt oder angezeigt. Die aktuellen Optionen sind ? die Variable SHELLOPTS zug?lich. Der Befehl verf?? folgende Optionen: -p (print) gibt eine Liste der aktuellen Einstellungen aus, -s (set) setzt die im Argument angegebene Option, -u (unset) l?t sie. Durch -q (quiet) wird die Ausgabe des Befehls unterdr?, wie dies in Skripten praktisch sein kann. Durch -o beschr?t sich die Wirkung von shopt auf die durch set -o gesetzten Optionen. In der folgenden Tabelle sind nur die wichtigsten mittels shopt einstellbaren Bash-Optionen aufgef?, eine vollst?ige Liste enth? die Manual-Page.

Option Funktion
cdable_vars bewirkt, dass die Bash Argumente des cd-Befehls als Variablen interpretiert, wenn es sich um keine Verzeichnisse handelt
cdspell einfache Schreibfehler (vertauschte oder fehlende Buchstaben) in Verzeichnisnamen werden durch diese Option automatisch korrigiert
checkhash die Bash sucht einen externen Befehl zun?st in der Hashtabelle, bevor er anhand des Suchpfades gefunden wird
checkwinsize wenn diese Option aktiviert ist, pr?die Bash nach jedem ausgef?en Befehl, ob sich die Terminal-Abmessungen ge?ert haben.
cmdhist zusammengeh?e Befehlszeilen werden in der History in Form einer Zeile abgelegt, dadurch vereinfacht sich ihre Bearbeitung
dotglob durch das Setzen dieser Option werden auch die mit einem Punkt beginnenden Dateinamen beim automatischen Komplettieren ber?ichtigt
execfail verhindert in Skripten, dass die Shell nach einem Fehler in einem exec-Befehl terminiert
histexpand bewirkt, dass Historydateien nicht mehr ?schrieben, sondern an bestehende Dateien angeh?t werden
lithist zusammen mit cmdhist bewirkt sie das Zusammenfassen mehrzeiliger Befehle
sourcepath der source-Befehl kann auf die PATH-Variable zugreifen, wenn diese Option gesetzt ist
expand_aliases erlaubt das Expandieren von Alias-Definitionen
nocaseglob bei der automatischen Dateinamenkomplettierung ber?ichtigt die Bash Gro?/Kleinschreibung nicht, wenn diese Option aktiv ist
huponexit allen von einer interaktiven Shell ausgef?en Hintergrundjobs wird ein SIGHUP-Signal gesendet, wenn sie terminiert
restricted_shell die Bash wird im Restricted-Modus mit eingeschr?ter Funktionalit?betrieben

2.7 Schlußbemerkung

Es gibt zwei Möglichkeiten, einem UNIX-Kommando beim Aufruf Informationen mitzugeben:
  • Auf der Kommandozeile
  • Über die Standardeingabe
Für die letztere Möglichkeit gibt es das Kommando cat Datei (concatenate): Lesen der angegebenen Datei und Kopieren auf die Standardausgabe. Mit cat Datei | Kommando bekommt man den Dateininhalt in die Standardeingabe des Kommandos.

Auch für die Ausgabe gibt es zwei Möglichkeiten:

  • Die Standardausgabe eines Programms kann durch die Backquotes (` `) oder durch $( ) als Parameter an ein Kommando übergeben werden.
  • Umgekehrt erlaubt das Kommando echo die Ausgabe der Kommandoparameter auf der Standardausgabe oder per Umleitung in eine Datei oder Pipe.
Wichtig werden diese Erkenntnisse erst bei Erstellen von Shell-Skripts, wo von allen geschilderten Möglichkeiten Gebrauch gemacht wird.

Zum Inhaltsverzeichnis Zum nächsten Abschnitt
Copyright © FH München, FB 04, Prof. Jürgen Plate