In diesem zweiten Teil der Serie über die Konfiguration der Bash wird es noch einmal praktisch: Das Einstellen des Prompts, und die für die Fehlersuche so nützlichen Tracing-Modi werden beschrieben.
In den letzten Teilen wurden immer wieder die unterschiedlichen Konfigurationsmöglichkeiten der Bash kurz vorgestellt. In diesem Teil werden sie systematisch zusammengefaßt und anhand von Beispielen näher erläutert.
Es gibt sechs Möglichkeiten, das Verhalten der Bash voreinzustellen bzw. das Programm zu konfigurieren:
- Über Befehlszeilenoptionen, die beim Aufruf der Bash bestimmte Modi einstellen oder andere Aktionen auslösen.
- Variablen beeinflussen das Verhalten der Bash in vielen Bereichen.
- Der Befehlszeileneditor kann durch die Funktionen der Readline-Library konfiguriert werden.
- Shell-Optionen werden mit dem eingebauten set-Befehl angezeigt und verändert.
- für die Verwendung erweiterter Shell-Optionen gibt es den eingebauten shopt-Befehl.
- Funktionen und Alias-Definitionen können den Aufruf externer Befehle verhindern und stattdessen andere Aktionen ausführen.
Alle diese Konfigurationsmöglichkeiten können wahlweise interaktiv (und damit temporär) erfolgen oder in den Konfigurationsdateien dauerhaft deklariert werden.
Befehlszeilenoptionen der Bash
Beim Aufruf der Bash können wie bei den meisten GNU-Programmen Optionen im zwei Formaten angegeben werden: Die Kurzoption -v bewirkt, dass ausführlichere Meldungen angezeigt werden. Dasselbe läßt sich auch durch die Langform -verbose erreichen. Die Kurzoptionen werden hauptsächlich für Moduseinstellungen (Optionen -abefhkmnptuvxBCHP und -o verwendet.
Die wichtigsten Befehlszeilenoptionen der Bash sind:
- -help: eine kurze Hilfe anzeigen.
- -login: die Shell immer als Login-Shell starten und damit die entsprechenden Konfigurationsdateien einlesen.
- -noprofile: als Login-Shell keine Konfigurationsdateien einlesen.
- -noediting: die Editier-Funktionen der Readline-Library deaktivieren.
- -rcfile: die im Argument angegebene Datei als Konfigurationsdatei einlesen.
- -c (commands): die im Argument angegebenen Befehle ausführen, nachdem alle anderen Optionen berücksichtigt wurden.
- -i: (interactive) die Bash als interaktive Shell starten und damit die entsprechenden Variablen setzen.
- -r oder -restricted: nur eine kleine Gruppe von Befehlen kann in diesem Modus verwendet werden, alle anderen Funktionen (etwa zum Wechseln der Verzeichnisses, zum Setzen von Variablen usw.) sind deaktiviert.
- –: alles was in der Befehlszeile rechts noch folgt, wird nicht mehr als Option für die Bash interpretiert.
Konfiguration durch Variablen
Die vielen Variablen der Bash wurden in den letzten Teilen schon mehrfach angesprochen, da sie die unterschiedlichsten Aspekte der Shell betreffen. Bisher nicht angesprochen wurden die Möglichkeiten, den Bash-Prompt zu konfigurieren. Über die Umgebungsvariablen $PS1 bis $PS4 können vier unterschiedlichste Prompt-Darstellungen definiert werden.
*
$PS1 wird als normaler Prompt verwendet, wie er nach dem Ausführen einer Befehlszeile als Eingabeaufforderung für weitere Befehle erscheint. Dieser Prompt wird von Anwendern oft individuell eingestellt, wie dies unten ausführlich gezeigt wird.
- $PS2 wird angezeigt, wenn eine Befehlszeile mittels [RETURN] umbrochen wird, aber noch nicht abgeschlossen ist, weil beispielsweise noch die schließende Klammer oder Quotes fehlen. Die Voreinstellung besteht aus einem fordernden > .
- $PS3 wird vom eingebauten select-Befehl verwendet und weist den Anwender auf verschieden Wahlmöglichkeiten hin. Voreingestellt ist #? .
- $PS4 erscheint nur im Tracing-Modus, also dann, wenn die Befehlszeilen vor der Bearbeitung angezeigt werden.
In den Prompt-Variablen können neben normalen Zeichen auch Steuerzeichen für das Terminal und einige spezielle Schlüssel verwendet werden, die durch die Bash ausgewertet werden und deren Ergebnis dann im Prompt erscheint. Tabelle 1 enthält eine Zusammenfassung dieser Schlüsselzeichen.
$> export PS1='\d_\t>' Thu Jan 18_02:14:35> $> export PS1='\#$' 120$
Wird durch \a das Bell-Zeichen in den Prompt aufgenommen, ertönt jedesmal die Display-Klingel (auf Dauer nervt das aber ganz schön…)
Weiterhin stehen die üblichen Variablen der Shell zur Verfügung. Dabei ist die Fehlervariable $? besonders nützlich. Mit ihr wird der Rückgabewert (Return code) des letzten Befehls dargestellt:
$> export PS1='$?>' 0> ls irgend-ein-Quatsch 1>
Sofern keine Datei oder kein Verzeichnis mit dem Namen irgend-ein-Quatsch vorhanden ist, erzeugt der Befehl einen Rückgabewert von 1. Dieser kann in einem Script ausgewertet werden; in einer interaktiven Shell ist er normalerweise nicht sichtbar. Mit dem oben verwendeten Prompt wird dieser Wert angezeigt.
Am Rande ein kleiner Tip von Edgar Greuter: wann immer die Konfiguration des Terminals durch die versehentliche Ausgabe einer Binärdatei verstellt wurde, hilft oft die Eingabe von [Ctrl][o]. Diese Zeichenkette kann an das Ende des $PS1-Prompts angefügt werden:
$> export PS1=$PS1^O
Achtung: vor der Eingabe von [Ctrl][o] auf einem Terminal (oder in einem Editor, der das Terminal verwendet) muß [Ctrl][v] eingegeben werden, damit die Zeichenkette^O in die Variable aufgenommen wird.
Befehle können übrigens auch für die Konstruktion der Prompts genutzt werden, wie folgendes Beispiel zeigt:
PS1="\\[\\033]0;\\u@\\h:\\w\\007\\][\$(date +%H%M)][\\033[1;m\\u@\\033[7;m\\h\\033[0m:\\w]\$ "
Dieser Prompt macht ausgiebigen Gebrauch von den Möglichkeiten durch Steuerzeichen bestimmte Teile der Ausgabe fett bzw. invers anzuzeigen. Die doppelten Backslash-Zeichen bewirken, dass dieses Zeichen selbst in die Variable aufgenommen wird. Das Ergebnis sieht dann folgendermaßen aus:
Die aktuelle Uhrzeit wird dabei durch den implizit ausgeführten Befehl date +%H%M ermittelt. Die Konstruktion $() bewirkt, dass der Inhalt der Klammern ganz zuerst ausgeführt wird und dass dieses Ergebnis dann in die Befehlszeile übernommen wird.
Nicht vergessen sollte man im Zusammenhang mit der Konstruktion von Prompt-Variablen die Umgebungsvariable $PROMPT_COMMAND. Der Inhalt dieser Variablen wird vor der Ausgabe des $PS1-Prompts immer ausgeführt. Damit stehen einem geschickten Shell-Programmierer sehr weitreichende Möglichkeiten offen. Er kann beispielsweise ein im aktuellen Verzeichnis vorhandenes Script (oder einen beliebigen Befehl) automatisch ausführen, er kann die History der Shell speichern und so die durchgeführten Aktionen automatisch protokollieren, er kann den Prompt immer wieder abhängig von bestimmten Gegebenheiten ändern usw. Oft wird diese Variable eingesetzt um – beispielsweise – die Titelzeile von Terminalfenstern mit dem Rechnernamen ($HOSTNAME) und dem aktuellen Verzeichnis ($PWD) zu verzieren:
> export PROMPT_COMMAND='echo -ne "\033]2;$HOSTNAME:$PWD$\007"'
Diese Methode funktioniert bei fast allen xterm-ähnlichen Terminalemulatoren, einschließlich rxvt und den KDE-Varianten.
Doch Achtung: PROMPT_COMMAND-Befehle sollten nur kleine, schnelle Aktionen ausführen, damit sich die Bearbeitung nicht unnötig verzögert. Und: nicht jeder Automatismus ist auch wirklich sinnvoll, manchmal ist weniger mehr… $? wird übrigens durch die PROMPT_COMMAND-Befehle beeinflußt!
Konfiguration der Readline-Library
Die Konfiguration des Befehlszeileneditors wurde im ersten Teil dieser Reihe kurz vorgestellt, worauf hier verwiesen wird. Dreh- und Angelpunkt der Konfiguration ist der bind-Befehl. Die voreingestellte Konfiguration erfolgt systemweit in der Datei inputrc im Verzeichnis /etc/ bzw. individuell durch .inputrc im Home-Verzeichnis des Anwenders. Das genaue Format und die Möglichkeiten dieser Datei wird in einer recht umfangreichen Man-Page und Info-Datei erklärt.
Der Tracing-Modus
Im Tracing-Modus kann die Bearbeitung von Befehlen verfolgt werden, obwohl die Bezeichnung eigentlich falsch ist, wie sich gleich zeigen wird.
Durch die Befehlszeilenoption -v bzw. die Option verbose wird die Bash plötzlich geschwätzig. Befehlszeilen werden vor der weiteren Bearbeitung so angezeigt, wie die Bash sie eingelesen hat.
$> echo ababcde ab1de ab2de ab3de $> set -v $> echo ababcde echo ab1,2,3de ab1de ab2de ab3de
Im ersten Fall wird die Befehlszeile eingeben und die Bash gibt das Ergebnis zurück. So funktioniert die Shell gewöhnlich. Durch set -v aktiviert der Anwender die Ausgabe der Befehlszeilen, was dann zu der Anzeige der ersten Zeile im zweiten Beispiel führt. Anschließend führt die Bash diese Zeile aus und stellt das Ergebnis in der letzten Zeile dar.
Gerade die Expandierungs-Möglichkeiten der Bash sind sehr leistungsfähig, aber leider nicht immer ganz einfach zu verstehen. Mirko Dölle beschreibt in seinem Artikel, wie sie funktionieren und was sie alles zu leisten Vermögen. Für die Fehlersuche in Befehlszeilen mit Expandierungen hat die Bash einen spezielle Modus. Die Option -x bzw. xtrace wird die Bash veranlaßt, Befehlszeilen so auszugeben, wie sie nach dem Expandieren von Argumenten und Klammerersetzungen vorliegen, aber bevor sie tatsächlich abgearbeitet werden.
$> set -x $> echo ab1,2,3de + echo ab1de ab2de ab3de ab1de ab2de ab3de
Hier kommt nun auch endlich der PS2-Prompt ins Spiel: zur Kennzeichnung von Zeilen, die nicht direkt eingegeben worden sind, sondern die durch das expandieren einer Befehlszeile durch die Bash selbst konstruiert worden sind, wird dieser Prompt ausgegeben. In diesem Beispiel zeigt sich also sehr schön, wohin das Expandieren des Klammerausdrucks führt, und dass die Bash die Expandierung via echo anzeigt. So richtig deutlich wird der Wert dieses Modus, wenn anstelle des echo-Befehls ein Alias oder eine Funktion zum Einsatz kommt:
$> ECHO () echo $*; + ECHO ab1de ab2de ab3de + echo ab1de ab2de ab3de ab1de ab2de ab3de
Zuerst ersetzt die Bash die Funktion ECHO durch den entsprechenden Befehl, wie dies in der zweiten Zeile angezeigt wird. Dann werden die weiteren Argumente (sprich der Klammerausdruck) expandiert und die so entstandene Befehlszeile erneut dargestellt. Ganz zum Schluß kommt dann das Ergebnis in einer eigenen Zeile.
Die Kombination beider Optionen führt zu dem sogenannten Monitor- oder Protokollmodus der Bash. Mit diesem Modus läßt sich beispielsweise das Ausführen von Scripten genau verfolgen.
Schlüssel für die Konstruktion des Prompts
| \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ührten Bash (2.03) |
| \V | Das Release der Bash, bestehend aus der Versionsnummer und dem Patchlevel (2.03.1) |
| \w | das aktuelle Arbeitsverzeichnis in ausführlicher 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üssen 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 |
Fazit
Die Konfiguration der Bash birgt keine unüberwindbaren Hindernisse. Im Gegenteil: Mit einigen kleine Tricks (und den einen oder anderen Tip) lassen sich viele Features der Shell sinnvoll einsetzen. Die Konfiguration geht weiter! In dem Artikel Der Dotfile-Generator wird ein universelles Tool zum Erzeugen von Konfigurationsdateien vorgestellt. Das geht dann noch einfacher und bietet darüberhinaus eine hübsche grafische Oberfläche…

