7.7 Grundlagen der Shellnutzung
Der folgende Abschnitt zählt zu den wichtigsten des Buches, da hier die elementaren Kenntnisse für die Handhabung der Shell vermittelt werden.
7.7.1 Programme starten
In der Shell werden Programme entweder durch Angabe des Programmnamens oder durch des genauen Pfades zum Programm gestartet.
Relative Pfadangabe
Beim Programmstart über den Namen durchsucht die Shell ihre interne Liste von Verzeichnissen, die sie in der angegebenen Reihenfolge nach dem jeweiligen Programmnamen durchsucht. Wird das Programm in einem dieser Verzeichnisse gefunden, so wird es gestartet.
Diese Verzeichnisliste ist in der Variablen $PATH gespeichert. Sie lernen im weiteren Verlauf des Kapitels noch den Umgang mit solchen Variablen. Um jedoch schon einmal einen Blick auf den Inhalt dieser Variablen zu werfen, können Sie den folgenden Befehl ausführen:
Listing 7.11 Inhalt der PATH-Variablen ausgeben
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
/usr/games
7.7.2 Kommandos aneinanderreihen
Unter Unix ist es generell möglich, mehr als nur ein Kommando pro Befehl durchzuführen. Ein Befehl endet erst, wenn er mit der Eingabetaste an die Shell geschickt wird. Ein Kommando kann von einem anderen einfach durch ein Semikolon (;) getrennt werden.
Stellen Sie sich einmal vor, Sie möchten fünf verschiedene Suchaktionen hintereinander starten, die aber jeweils eine unbestimmt lange Zeit benötigen werden. Eventuell müssen Sie so stundenlang vor dem Computer sitzen und warten, bis eine Suche nach der anderen durchgelaufen ist, um die jeweils folgende zu starten.
Viel einfacher wäre es da, wenn Sie alle Suchkommandos aneinanderreihen und einfach in einer Stunde mal vorbeischauen könnten, ob der Rechner die Aufgaben inzwischen erledigt hat. So müssen Sie nicht nach jeder einzelnen Suche die nächste starten.
Der Operator ;
Bewerkstelligt wird eine solche Reihung von Kommandos im einfachsten Fall durch Verwendung des Trennungsoperators, des Semikolons. Ungeachtet dessen, ob es Probleme mit einem der Kommandos in der Liste gibt, die Sie der Shell übergeben, laufen alle Kommandos hintereinander ab. Dies bedeutet allerdings auch, dass Probleme entstehen können, wenn ein Befehl auf dem anderen aufbaut. [Fn. Beispielsweise könnte das Kommando, das ein Backup erstellt, fehlschlagen und das Kommando, das dieses Backup auf einen Storage-Server übertragen soll, dann eine beschädigte Datei übertragen.]
Listing 7.12 Der Trennungsoperator
$ ls VerZeiCh ; uname ; find / -name Datei
/bin/ls: VerZeiCh: No such file or directory // ls
Linux // uname
/usr/local/share/Datei // find
/home/user/Datei
Der Operator &&
Verwenden Sie hingegen den &&-Operator, so werden die dadurch aneinandergereihten Kommandos nur so lange ausgeführt, wie der Ablauf der in der Liste angegebenen Kommandos erfolgreich ist. Die Abarbeitung der Kommandoreihe wird also abgebrochen, sobald ein Fehler auftritt. Dies ist allerdings nicht ganz exakt formuliert, denn ein Abbruch gilt nur dann als Fehler, wenn ein Programm mit einem entsprechenden Fehlercode endet.
Unter Unix-Systemen gibt jedes Programm beim Beenden einen Wert an die Shell zurück. Dieser Wert ist entweder 0, wenn das Programm erfolgreich ausgeführt wurde, oder ungleich 0, wenn ein Problem auftrat. In der C-Programmierung wird beispielsweise durch das return-Schlüsselwort in der Funktion int main(...) ein solcher Wert zurückgegeben.
Wenn wir das obige Beispiel nun erneut aufrufen und dabei die Semikolon-Operatoren durch &&-Verknüpfungen ersetzen, werden wir feststellen, dass die Kommandoreihe nicht weiter ausgeführt wird, nachdem das ls-Kommando fehlgeschlagen ist.
Listing 7.13 Der Operator &&
$ ls VerZeiCh && uname && find / -name Datei
/bin/ls: VerZeiCh: No such file or directory
Der ||-Operator
Das Gegenstück zum &&-Operator ist der ||-Operator. Anders als bei && werden die durch || aneinandergereihten Kommandos nur dann ausgeführt, wenn das vorherige Kommando fehlschlägt. Man verwendet diesen Operator besonders gerne zur Ausgabe von Fehlermeldungen und zum Ausführen von »Plan B«.
Listing 7.14 Beispielanwendung des ||-Operators
pgrep X >/dev/null || echo "use 'startx' to start X"
7.7.3 Mehrzeilige Kommandos
Oftmals ist es recht unübersichtlich und unangenehm, sehr lange Kommandolisten oder lange Einzelbefehle zu übergeben. Viel einfacher ist es hingegen, diese auf mehrere Zeilen zu verteilen. Diese mehrzeiligen Kommandos werden mit einem Backslash (\) realisiert.
Im Folgenden übergeben wir find das zweite und dritte Element des Argument- vektors in einer neuen Zeile:
Listing 7.15 Ein Kommando über mehrere Zeilen
$ find /usr/local/share/doc/usd \
-name bc \
/usr/share/doc/usd/06.bc/bc
7.7.4 Alias, shell-intern oder -extern?
Wie Sie bereits wissen, ist es in der Shell möglich, normale Programme zu starten. Weiterhin gibt es die Möglichkeit, shell-interne Kommandos auszuführen.
type
Je nach Shell sind verschiedene Kommandos in der Shell selber integriert. Die bash enthält beispielsweise ein eigenes kill-Kommando. Wird also in der bash kill aufgerufen, so wird nicht das Programm aus dem Verzeichnis /bin, sondern das gleichnamige Shell-Builtin gestartet. Da die Shell-Builtins von Shell zu Shell variieren, können wir Ihnen leider nicht allgemein gültig sagen, welche Kommandos shell-intern sind. Zur Lösung des Problems gibt es jedoch das Kommando type (das ebenfalls ein Shell-Builtin der bash ist [Fn. Auch andere Shells, etwa die Z-Shell, bieten diese Funktionalität.]). An type muss lediglich der Name eines Kommandos oder Programms als Parameter übergeben werden. Daraufhin gibt type aus, ob es sich dabei um ein Shell-Builtin oder um ein Programm handelt, dessen absoluter Pfad dann ausgegeben wird.
Listing 7.16 Verwendung des Kommandos type
$ type type
type is a shell builtin
$ type bash
bash is /bin/bash
[»]Es ist zu beachten, dass type – sofern für den übertragenen Parameter sowohl eine Programmdatei als auch ein Shell-Builtin zur Verfügung stehen – nur ausgeben wird, dass ein Builtin vorhanden ist.
Listing 7.17 kill ist Programm und Builtin
$ type kill
kill is a shell builtin
$ ls /bin/kill
/bin/killwhich
In der Grundfunktionalität identisch, jedoch dank einer Option etwas informativer ist das Programm which. Dieses Programm ist in einigen Shells als Builtin vorhanden, existiert aber auch als Programmdatei. which hat die Fähigkeit, über den Parameter -a alle gefundenen Einträge für einen übergebenen Namen auszugeben. [Fn. Einige type-Implementierungen unterstützen dieses Feature ebenfalls.] Das bedeutet nichts anderes, als dass, wenn kill als Shell-Builtin vorhanden ist, sowohl diese Information als auch der Pfad der Binärdatei in /bin ausgegeben wird. Zudem durchsucht which alle in der Variable $PATH angegebenen Verzeichnisse nach der entsprechenden Datei. Ist beispielsweise which sowohl in /usr/bin als auch in /bin vorhanden, findet es (sofern $PATH entsprechend gesetzt ist) beide Dateien.
Listing 7.18 Das Programm which
$ which -a which
which: shell built-in command
/usr/bin/which
Alias?
In der Shell kann ein so genanntes Alias angelegt werden. Das ist ein Befehl, der einen anderen ersetzt – dazu später mehr. type, which und whence (je nach verwendeter Shell) geben Ihnen auch darüber Auskunft, ob ein Kommando ein solches Alias ist.
Listing 7.19 Alias-Überprüfung
$ type ls
ls is an alias for /bin/ls -aF
$ which -a ls
ls: aliased to /bin/ls -aF
/bin/ls
$ whence -va ls
ls is an alias for /bin/ls -aF
ls is /bin/ls
7.7.5 Shell-Aliase
Shell-Aliase bieten eine Möglichkeit zur Kommandosubstitution. Sie erlauben es, einen neuen Befehlsnamen zu vergeben, der stellvertretend für ein Kommando oder eine Kommandoreihe steht. Ein Alias wird über das gleichnamige Kommando alias erstellt und modifiziert. Eine Liste der bereits vorhandenen Alias-Einträge können Sie ebenfalls ausgeben lassen.
Listing 7.20 Aktuelle Alias-Liste anzeigen
$ alias
cl="cd ..;ls"
cll="cd ..;ll"
ll="ls -alhoF"
ls="/bin/ls -aF"
Der Vorteil liegt auf der Hand: Wenn Sie beispielsweise ständig das Kommando ls -laFh ausführen und sich dafür das Alias ll erstellen, sparen Sie Zeit und vertippen sich dabei nicht. Zudem können einem Alias auch Parameter übergeben werden. Dem Alias ll können also auch ein Dateiname und weitere Parameter für das ls-Programm übergeben werden.
Listing 7.21 der Alias ll
$ ll ../eil2/buch.ps
-rw------- 1 sw sw 37.7M Feb 20 13:55 ../eil2/buch.ps
Ein Alias erstellen und modifizieren
Ein Alias erstellt man, indem man den neuen Befehlsnamen sowie den Befehl, der hinter diesem verborgen sein soll, dem alias-Kommando übergibt. Erstellen wir beispielsweise einmal ein Alias, um den SSH-Login auf einem Host zu automatisieren:
Listing 7.22 Alias verwenden
$ alias ssh_milk='export TERM=xterm;ssh swendzel@192.168.0.2'
Ein Alias kann modifiziert werden, indem ihm einfach erneut ein (anderer) Befehl zugewiesen wird.
Ein Alias löschen
Manchmal möchte man eine erstelltes Alias auch wieder löschen. Dies wird ganz einfach dadurch bewerkstelligt, dass man dem Kommando unalias den entsprechenden Namen des Alias übergibt.
Listing 7.23 Das unalias-Kommando
$ alias system="uname -sr"
$ system
OpenBSD 3.6
$ unalias system
$ system
zsh: command not found: system
7.7.6 Verzeichniswechsel
Im letzten Kapitel haben Sie bereits die wichtigsten Grundlagen kennengelernt, um sich frei durch den Verzeichnisbaum zu bewegen, sprich: Verzeichnisse zu wechseln (cd), das aktuelle Arbeitsverzeichnis auszugeben (pwd) und den Inhalt von Verzeichnissen auszugeben (ls).
Im Folgenden wollen wir uns mit einigen teilweise konfigurationsspezifischen Möglichkeiten beschäftigen, die Ihnen, was den Verzeichniswechsel anbelangt, die tägliche Tipperei erleichtern werden. Wahrscheinlich werden Sie auf diese Arbeitsweise, nachdem Sie sich erst einmal an selbige gewöhnt haben, nicht wieder verzichten wollen.
Die ersten zwei Tipps (cd . und cd ..) kennen Sie bereits aus dem vorherigen Kapitel – sie werden hier jedoch der Vollständigkeit halber ebenfalls erläutert.
».«
Der Punkt (.) gibt das aktuelle Arbeitsverzeichnis an. Sie benötigen ihn entweder, wenn Sie in das Verzeichnis wechseln wollen, in dem Sie sich momentan befinden [Fn. Nun ... zumindest ist dies möglich – der Sinn solch einer Aktion soll an dieser Stelle nicht diskutiert werden.] (optional, wenn Sie auf eine Datei im aktuellen Verzeichnis zugreifen möchten), aber vor allen Dingen dann, wenn Sie ein Skript oder Programm im Arbeitsverzeichnis ausführen möchten.
Listing 7.24 Ein Skript im aktuellen Verzeichnis ausführen
$ pwd
/home/user
$ cd .
$ pwd
/home/user
$ ./script.sh
...
»..«
Verwenden Sie hingegen zwei Punkte, so stehen diese stellvertretend für das nächsthöhere Verzeichnis in der Hierarchie. Dies bedeutet, dass Sie, wenn Sie sich beispielsweise im Verzeichnis /usr/local/bin befinden, mittels cd .. in das Verzeichnis /usr/local wechseln können. Diese zwei Punkte können auch durch Slashes mehrfach verkettet werden.
Listing 7.25 Verzeichnisebene wechseln mit »..«
$ pwd
/usr/local/bin
$ cd ../../include
$ pwd
/usr/include
»~-«
Geben Sie die zwei Zeichen ~- beim Verzeichniswechsel an, so wechselt die Shell anschließend wieder in das Verzeichnis, in dem Sie sich vor dem letzten Verzeichniswechsel befanden. Hier ein verdeutlichendes Beispiel, denn beim Zuschauen lernt man ja schließlich am besten:
Listing 7.26 Ins vorherige Verzeichnis zurückkehren
$ pwd
/usr/local/bin
$ cd /etc
$ pwd
/etc
$ cd \~{}-
$ pwd
/usr/local/bin
»~«
Geben Sie für den Verzeichniswechsel eine Tilde (~) an, so wechseln Sie in Ihr Heimatverzeichnis. Verwendet man hingegen die Tilde in Verbindung mit einem Benutzernamen, so wechselt die Shell in das Heimatverzeichnis des jeweiligen Benutzers, was natürlich nur funktioniert, wenn man auch die entsprechenden Zugriffsrechte für diese Aktion hat. [Fn. Dazu muss sowohl das Lese- als auch das Ausführrecht gegeben sein, also (mindestens) r-x.]
$HOME und » «
Wechseln Sie mit der Variable $HOME das Verzeichnis, so kommen Sie – Sie werden es bereits ahnen – ebenfalls in das eigene Heimatverzeichnis. Die Verwendung der $HOME-Variable ist allerdings nur möglich, wenn diese auch (korrekt) gesetzt ist, was bis auf einige Ausnahmesituationen immer der Fall sein sollte.
Derselbe Wechsel in das Heimatverzeichnis ist möglich, indem man dem Kommando cd einfach gar keinen Parameter übergibt.
Listing 7.27 Trautes Heim
$ pwd
/etc
$ cd $HOME; pwd
/home/user
$ cd /etc; cd; pwd
/home/user
7.7.7 echo
Beschäftigen wir uns nun mit einem grundlegenden Programm, das in den meisten Shells allerdings auch als Builtin vorhanden ist. Die Rede ist von echo. Dieses Kommando gibt den ihm übergebenen Text auf der Konsole aus und ist besonders nützlich in der Shellskriptprogrammierung, etwa zum Einsehen von Variablenwerten.
Wir benötigen echo noch sehr oft im weiteren Verlauf des Kapitels, u. a. bei der Kommandosubstitution und wie bereits erwähnt bei der Shellskriptprogrammierung. Die Verwendung des Kommandos ist denkbar einfach: Der auszugebende Text wird als Parameter übergeben und sodann von echo ausgegeben.
Listing 7.28 Das Kommando echo
$ echo "Hallo, Welt\!"
Hallo, Welt!
Wie Ihnen vielleicht aufgefallen ist, gibt es hierbei doch etwas zu beachten: Einige Sonderzeichen, wie im obigen Beispiel das Ausrufezeichen, müssen durch Escape-Sequenzen eingeleitet werden, da diese Zeichen ansonsten andere Aktionen einleiten. Später werden Sie einige solcher Sonderzeichen kennenlernen, etwa das Dollarzeichen ($), das für Variablen Verwendung findet.
Zunächst einmal werden wir solche Probleme durch Hochkommata umgehen. Alles, was Sie in Hochkommata stellen, wird von der Shell nicht weiter interpretiert, echo gibt es dann einfach aus.
Listing 7.29 echo in Verwendung mit Hochkommas
$ echo 'Hallo, Welt!'
Hallo, Welt!
7.7.8 Shellvariablen
Ein wichtiges Werkzeug im Umgang mit der Shell, insbesondere bei der Skriptprogrammierung, sind Variablen. Einer Variablen können Sie einen Wert zuweisen, auf den Sie später wieder (und beliebig oft) zugreifen können. Solch ein zugewiesener Wert kann eine Zahl, die Ausgabe eines ganzen Programms oder ein String, also eine Zeichenkette wie »Hallo, Welt!«, sein.
Zuweisung von Werten
Variablen werden über einen wählbaren Namen vergeben. Nehmen wir einmal an, der Name eines glorreichen Getiers, nämlich Felix, solle in einer Variable gespeichert werden. Es wäre beispielsweise sinnvoll, dieser Variable den Namen »KATZE« oder »KATZENNAME« zu geben. In der Regel schreibt man Shellvariablen übrigens in Großbuchstaben; dies ist jedoch nicht zwingend notwendig! Die Zuweisung erfolgt in der Familie der Bourne-Shell [Fn. In der Familie der C-Shell muss hierzu das Shell-Builtin set verwendet werden.] durch ein Gleichheitszeichen:
Listing 7.30 Der Variable KATZE den Wert »Felix« zuweisen
$ KATZE=Felix
Durch eine erneute Zuweisung eines Wertes wird der alte Variablenwert überschrieben.
Abfrage von Werten
Um den Wert einer Variablen einzusehen, kann unter anderem echo verwendet werden. Die Shell übergibt echo in diesem Fall den Inhalt der angegebenen Variablen, so dass echo nicht mitbekommt, dass es einen Variableninhalt ausgibt. Die beiden folgenden Befehle bewirken folglich dasselbe:
Listing 7.31 echo mit und ohne Variable
$ echo Felix
Felix
$ echo $KATZE
Felix
Beachten Sie, dass beim Zugriff auf eine Variable ein Dollarzeichen ($) vor den Namen der Variablen gesetzt werden muss, sonst interpretiert die Shell diesen als String:
Listing 7.32 Fehler: Dollarzeichen vergessen
$ echo KATZE
KATZE
Löschen von Variablen
Um eine Variable wieder zu löschen, muss deren Name nur dem unset-Kommando übergeben werden.
Listing 7.33 Das Kommando unset
$ echo $KATZE
Felix
$ unset KATZE
$ echo $KATZE
$
Variablen in Text einbetten und ausgeben
Um eine Variable in den Text einer Ausgabe (oder in den Wert einer anderen Variablen) einzubauen, gibt es zwei Herangehensweisen.
Die erste Möglichkeit besteht darin, die Variable, wie bereits mit echo gezeigt, in der Form $NAME zu verwenden, was fast immer problemlos funktioniert.
Listing 7.34 Variable im Text
$ echo "Herzlich willkommen, $KATZE\!"
Herzlich willkommen, Felix!
Gehen wir nun davon aus, dass wir neben der Variable KATZE noch eine zweite Variable mit dem Namen KATZE2 benutzen. Für den Fall, dass Sie den Wert von KATZE und direkt danach eine »2« ausgeben möchten, können Sie nun nicht mehr die soeben besprochene Variante verwenden, sondern müssen den Variablennamen in geschweifte Klammern setzen. Das ist nötig, um dessen Anfang und Ende genau zu markieren.
Listing 7.35 Variable im Text
$ KATZE2="Mauzi"
$ echo "Herzlich willkommen, $KATZE2\!"
Herzlich willkommen, Mauzi!
$ echo "Herzlich willkommen, ${KATZE}2\!"
Herzlich willkommen, Felix2!
[»]Mehr zur Einbettung von Variablenwerten in Text oder andere Variablenwerte erfahren Sie in Abschnitt 7.7.9, »Kommandosubstitution«.
Vorhandene Variablen anzeigen lassen
Alle aktuell vorhandenen Variablen sowie die Werte, die diesen zugewiesen wurden, können Sie mittels des set-Kommandos einsehen. Dabei werden sowohl lokale als auch globale Variablen angezeigt (mehr dazu im nächsten Absatz). [Fn. In einigen Shells gibt set noch zusätzliche Informationen, etwa Shellfunktionen, aus.]
Listing 7.36 set, ausgeführt in der Z-Shell
$ set
...
XCURSOR_SIZE=""
XCURSOR_THEME=""
XYRIA=/home/swendzel/projekte/xyria_
ZSH_NAME=zsh
ZSH_VERSION=4.2.1
_=set
aliases
...
Variablen einlesen
Selbstverständlich kann man auch den Wert einer Variablen von der Tastatur einlesen lassen. Dies wird über das Builtin read bewerkstelligt. Man übergibt read den Namen der gewünschten Variablen (ohne das Dollarzeichen davor). Die Eingabe wird durch die Eingabetaste beendet.
Listing 7.37 read verwenden
$ read Name
Felix
$ echo $Name
Felix
Einige Shells unterstützten weitere Parameter für read. So kann etwa mit dem Parameter -n ANZAHL die Anzahl der einzulesenden Zeichen angegeben werden. Mit -s wird hingegen die Eingabe des Benutzers nicht angezeigt. Mit read -s -n 8 pw würde also ein maximal achtstelliger Wert in die Variable »pw« eingelesen und die eingegebenen Zeichen nicht angezeigt.
Schreibgeschützte Variablen
Variablen können mit einem Schreibschutz versehen werden. Damit lässt sich sicherstellen, dass ihr Wert nicht aus Versehen wieder verändert wird. Hierzu wird dem readonly-Kommando einfach der Name der jeweiligen Variablen übergeben. Übergeben Sie readonly keinen Parameter, so erhalten Sie eine Liste aller derzeit schreibgeschützten Variablen.
Globale und lokale Variablen
Eben sprachen wir bereits an, dass es sowohl lokale als auch globale Variablen gibt. Wir wollen Ihnen selbstverständlich nicht den Unterschied zwischen diesen beiden Variablenarten vorenthalten.
Eine globale Variable wird im Gegensatz zu einer lokalen an Unterprogramme übergeben. Viele Programme nutzen dieses Feature, etwa das Programm BitchX, ein freier IRC-Client. Dieser greift für die Konfiguration der IRC-Verbindung auf globale Variablen zurück:
Listing 7.38 Globale Variablen für BitchX
IRCNAME="Steffen W"
IRCNICK=cdp_xe
IRCPORT=6667
IRCSERVER=milk.sun
Würden Sie nun das Programm bitchx aus einer Shell mit diesen globalen Variablen starten, so würde
es deren Werte verwenden.
export
Um sich eine Liste der globalen Variablen, die aktuell in der Shell geladen sind, anzeigen zu lassen, müssen Sie nur das Kommando export aufrufen.
Globale Variablen erzeugen
Mittels export können Sie übrigens auch globale Variablen erstellen. Sie gehen dabei wie bei der
Erstellung von lokalen Variablen vor, nur dass Sie den Erzeugungsbefehl dem Kommando export übergeben.
Listing 7.39 Erzeugen einer globalen Variablen
$ export KATZE=Felix
$ export | grep KATZE
KATZE=Felix
Auch globale Variablen können mit dem Kommando unset wieder gelöscht werden.
Die wichtigsten globalen Variablen
Es gibt einige globale Variable, die für die Nutzung des Unix-Betriebssystems äußerst wichtig sind und daher bekannt sein sollten. Wir haben sie sowie ihre Bedeutung in einer kleinen Tabelle zusammengefasst. Einige spezielle Variable wie $? werden wir im Verlauf des Kapitels (nämlich bei der Shellskriptprogrammierung) noch genauer besprechen.
Variable | Bedeutung |
$HOME |
Heimatverzeichnis des Benutzers |
$LOGNAME und teilweise auch $USER |
Loginname des Benutzers |
$PATH |
Liste von Verzeichnissen, die nach einer relativ angegebenen, ausführbaren Datei durchsucht werden sollen (siehe Seite #$refpage#PATH#). |
$PS1 bis $PS4 |
Kommandozeilen-Prompt (detailliert beschrieben im folgenden Abschnitt) |
$RPS1 |
Prompt am rechten Konsolenrand in der Z-Shell |
$TERM |
verwendetes Terminal, z. B. »xterm-color« |
$0 |
Name des aktuellen Prozesses |
$$ |
aktuelle Prozess-ID |
$n |
der einem Skript oder einer Skriptfunktion übergebene Parameter Nummer »n« |
$# |
Gesamtzahl der an eine Funktion oder ein Skript übergebenen Parameter |
$? |
Rückgabewert des zuletzt in dieser Shell beendeten Prozesses |
$ und $@ |
alle dem Skript oder einer Funktion übergebenen Parameter |
$! |
Prozess-ID des letzten Hintergrundprozesses |
$_ |
letzter Parameter des zuletzt ausgeführten Befehls |
Der Shell-Prompt
Eine Shell verfügt über einen Standardprompt und einige Nebenprompts. Doch was ist eigentlich solch ein Prompt? Im Prinzip ist ein Prompt eine Ausgabe von Textzeichen, die Sie zur Eingabe eines Kommandos auffordert. Je nach verwendeter Shell und der persönlichen Konfiguration der entsprechenden Variablen kann solch ein Prompt ganz unterschiedlich aussehen. Hier im Buch haben wir meistens user$ und $ als Benutzerprompt, sowie root# und # als Prompt des Superusers verwendet, was typisch für eine Unix-Shell ist.
Jeder Prompt wird über eine bestimmte Variable festgelegt. Der primäre Prompt nennt sich PS1, diesen sehen Sie standardmäßig. Versuchen Sie einmal, diesen Prompt zu löschen mit
\begin{gpListing}
$ unset PS1
Sie werden feststellen, dass nun jegliche Eingabeaufforderung fehlt. Sie können allerdings nach wie vor Befehle ausführen. Um das Prompt wiederherzustellen, können Sie die Variable PS1 wieder global setzen – eine passende Übung zur frisch erlernten Variablenbenutzung. [Fn. Hier eine mögliche Lösung: export PS1="\$ "] Mit dem Prompt lassen sich allerdings noch einige andere Spielereien anstellen. Beispielsweise können Sie, um sich die Arbeit zu erleichtern, das aktuelle Arbeitsverzeichnis oder den Benutzernamen, mit dem Sie derzeit arbeiten, anzeigen lassen.
Dazu müssen Sie sogenannte Escape-Sequenzen in die PS1-Variable einbauen. Eine Escape-Sequenz ist einfach eine Buchstabenfolge (oder ein einzelner Buchstabe), die durch einen vorangestellten Backslash auf eine bestimmte Art von der Shell interpretiert wird. Die Escape-Sequenzen für die Prompt-Konfiguration sind allerdings von Shell zu Shell verschieden, weshalb wir uns im Folgenden auf die bash konzentrieren.
Sequenz | Wirkung |
\a |
Ausgabe eines Tons im PC-Speaker (nervt) |
\d |
Zeigt das Datum an. |
\e |
Escape-Zeichen |
\h |
der Hostname (z. B. 'rechner') |
\H |
FQDN-Hostname (z. B. 'rechner.netzwerk.edu') |
\j |
Anzahl der Hintergrundprozesse |
\l |
Name des Terminals |
\n |
neue Zeile (Prompts können tatsächlich über mehrere Zeilen verteilt werden) |
\r |
Carriage-Return |
\s |
Name der Shell |
\t |
Zeit im 24-Stunden-Format |
\T |
Zeit im 12-Stunden-Format |
\@ |
Zeit im AM/PM-Format |
\u |
Name des Benutzers |
\v |
Version der bash |
\V |
\v, jedoch mit Patch-Level |
\w |
Gibt das Arbeitsverzeichnis an. |
\W |
Gibt nur das aktuelle Arbeitsverzeichnis ohne höhere Ebenen der Verzeichnishierarchie an. |
\# |
Anzahl der bereits aufgerufenen Kommandos während der Shell-Session des Terminals |
\$ |
Ist man als normaler Benutzer eingeloggt, so erscheint ein Dollarzeichen, root bekommt eine Raute (#) zu sehen. |
\\ |
ein Backslash |
Für besonders Interessierte ...
Es existieren noch weitere Escape-Sequenzen, beispielsweise zur Festsetzung der farblichen Hervorhebung. Diese werden im Rahmen dieses Buches jedoch nicht behandelt, da sie nicht auf allen Terminals funktionieren.
Einige Distributionen und sehr viele Benutzer verwenden die Variante Benutzer@Host Verzeichnis$, die ein an dieser Stelle besonders gut passendes Beispiel zur Nutzung von Escape-Sequenzen darstellt.
Listing 7.40 Setzung des bash-Prompts mit Escape-Sequenzen
user$ PS1="\u@\h \w\$"
swendzel@deb-sid /usr$ ls
...
Weitere Prompts
Neben dem Standard-Prompt $PS1 gibt es noch weitere Prompts:
$PS2..4Zum einen sind dies die
Eingabeaufforderungen zur Vervollständigung von Shellanweisungen (hiermit sind beispielsweise if-Anweisungen gemeint, die Sie in der Shellskriptprogrammierung kennenlernen werden). Sie werden (je nach Shell) mit $PS2 ... $PS4 bezeichnet. Da diese Prompts fast nie verwendet werden, behalten die meisten Benutzer ihre Standardkonfiguration bei.
$RPS1
Außerdem gibt es in der Z-Shell den $RPS1-Prompt. Dieser Prompt ist ein rechtsseitiger Prompt, den man beispielsweise sehr gut nutzen kann, um sich Uhrzeit und Datum ausgeben zu lassen.
7.7.9 Kommandosubstitution
Die Kommandosubstitution bietet Ihnen – besonders in der Shellskriptprogrammierung – die Möglichkeit, durch etwas Einfaches etwas sehr Nützliches zu erreichen. Sie erlaubt es Ihnen nämlich, die Ausgaben eines Programms direkt in einer Variable zu speichern oder als Parameter für andere Programme zu verwenden.
Erst einmal ganz einfach ...
Für diese Kommandosubstitution werden spezifische Einbettungszeichen verwendet, die sogenannten Backticks [Fn. Auf einer PC-Tastatur drückt man für diese Zeichen Shift und ` (Backtick, das ist die Taste neben ?\]). Alles, was Sie innerhalb dieser Zeichen schreiben, wird von der Shell als Befehl interpretiert. Dessen Ausgabe wird für alles Weitere, also etwa für die Zuweisung an eine Variable, verwendet.
Schauen wir uns die Anwendung der Backticks einmal an. Im folgenden Beispiel weisen wir der Variablen $OUTPUT die Ausgabe des ls-Befehls zu.
Listing 7.41 Kommandosubstitution
user$ OUTPUT=`ls`
user$ echo $OUTPUT
CVS
Makefile
TODO
ZEITPLAN
anhg_komref.aux
anhg_komref.tex
buch.dvi
buch.idx
buch.ilg
buch.ind
...
Wie Sie sehen, kann die Variable sofort weiterverwendet werden, indem man sie wie im Beispiel einem Programm wie echo übergibt. Vielleicht fragen Sie sich bereits, ob man eine Kommandosubstitution nicht auch direkt ohne Zwischenspeicherung in einer Variable an einen anderen Befehl übergeben kann. Mit dieser Vermutung haben Sie Recht, wie das folgende Listing zeigt.
Das ls-Programm (siehe Anhang B, »Kommandoreferenz«, auf Seite #$refpage#kr_ls#) soll uns Detailinformationen zu den einzelnen Dateien des Verzeichnisses ausgeben. Diese übergeben wir jedoch über eine Kommandosubstitution. Dies ist nicht sonderlich sinnvoll, verdeutlicht aber sehr gut die Funktionsweise der direkten Kommandosubstitution.
Listing 7.42 Direkte Kommandosubstitution
user$ ls -l `ls`
-rw------- 1 cdp_xe cdp_xe 707 Mar 15 15:45 Makefile
-rw------- 1 cdp_xe cdp_xe 289 Feb 20 14:10 TODO
-rw------- 1 cdp_xe cdp_xe 1809 Mar 17 14:16 ZEITPLAN
-rw------- 1 cdp_xe cdp_xe 2076 Mar 17 19:23 anhgkf.tex
-rw------- 1 cdp_xe cdp_xe 227844 Mar 17 19:24 buch.dvi
-rw------- 1 cdp_xe cdp_xe 2126 Mar 17 19:24 buch.idx
-rw------- 1 cdp_xe cdp_xe 413 Mar 17 19:24 buch.ilg
...
[»]Dieser Aufruf ist nicht mit einem bloßen Aufruf von ls -l gleichzusetzen, da hier Verzeichnisdateien die Ausgabe eines gesamten Verzeichnisinhalts bewirken. Solche feinen Unterschiede sollten bei der Kommandosubstitution generell bedacht werden. Da Sie jedoch schon einige Erfahrung mit Shells haben müssen, um überhaupt an solche Unterschiede zu denken, hilft nur eines: Spielen Sie mit der Shell!
Beachten Sie, dass die Kommandosubstitution nur die Standardausgabe eines Befehls liefert – Fehlermeldungen werden über die Standardfehlerausgabe geliefert und bleiben daher unentdeckt!
Diese Kommandosubstitution ist leider nicht immer ohne Weiteres möglich. Dies gilt auch für die Verwendung von Variablen. Es gibt hier feine, aber entscheidende Unterschiede. Es gibt nämlich verschiedene Arten, wie Text oder Anweisungen eingeschlossen werden können: in Hochkommata, Backticks oder Anführungszeichen. Jede dieser drei Möglichkeiten hat andere Folgen. Nehmen wir im Folgenden einmal an, der Variablen $VAR wurde der Text »hallo« zugewiesen.
Anführungszeichen
In Anführungszeichen werden sowohl Variablenwerte als auch Kommandosubstitutionen umgesetzt.
Listing 7.43 Anführungszeichen
$ echo "$VAR `pwd`"
hallo /home/cdp_xe/books/kompendium
Backticks
In Backticks werden Kommandosubstitutionen eingeschlossen. Variablenwerte werden hierbei als Kommando interpretiert.
Listing 7.44 Backticks
$ echo `$VAR` `pwd`
zsh: command not found: hallo
/home/cdp_xe/books/kompendium
Als Alternative zu den Backticks kann auch die Notation $( Kommando ) genutzt werden.
Hochkommata
In Hochkommata sind sowohl Variablenangaben als auch explizit in Backticks angegebene Kommandosubstitutionen wirkungslos.
Listing 7.45 Hochkommata
$ echo '$VAR `pwd`'
$VAR `pwd`
Ihr Kommentar
Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.