3.7 Grundlagen der Shell-Nutzung
Wie gesagt wollen wir mit den Grundlagen der Shell-Nutzung beginnen. Dieses Unterkapitel ist im Übrigen eines der wichtigsten des Buches, da hier die elementaren Kenntnisse für die Handhabung der Shell vermittelt werden.
3.7.1 Programme starten
In der Shell werden Programme entweder durch Angabe des Programmnamens oder durch die genaue Pfadangabe des Programms gestartet.
Relative Pfadangabe
Gibt man nicht den vollständigen Pfad eines Programms, sondern nur dessen Namen an, ist es ebenfalls möglich, dieses zu starten. Die Shell hat intern eine Liste von Verzeichnissen, die sie in der angegebenen Reihenfolge nach dem jeweiligen Programmnamen durchsucht. Wird das Programm in einem dieser Verzeichnisse gefunden, wird es gestartet.
Diese Verzeichnisliste wird in der Variable $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 Variable zu werfen, können Sie den folgenden Befehl ausführen:
$ echo $PATH /usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/loc al/bin:/usr/local/sbin:/usr/X11R6/bin:/usr/local/jdk1 .1.8/bin:
Listing 3.10 Inhalt der PATH-Variable ausgeben
3.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 jedoch simplerweise durch ein Semikolon (;) getrennt werden.
Stellen Sie sich einmal vor, Sie möchten 5 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 doch, wenn Sie alle Suchkommandos aneinanderreihen und einfach in einer Stunde mal vorbeischauen, ob der Rechner die Aufgaben bereits erledigt hat. So müssen Sie nicht nach jeder einzelnen Suche die nächste starten.
Der ;-Operator
Bewerkstelligt wird dies im einfachsten Fall durch Verwendung des Trennungsoperators, eben des Semikolons.
Ungeachtet dessen, ob es Probleme mit einem der Kommandos in der Kommandoreihenfolge 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. <Beispielsweise könnte das Kommando, das ein Backup erstellt, fehlschlagen und das Kommando, das dieses Backup auf einen Storage-Server überträgt, dann eine beschädigte Datei übertragen.>
$ 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
Listing 3.11 Der Trennungsoperator
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. Das bedeutet kurz gesagt, dass die Abarbeitung der Kommandoreihe abgebrochen wird, 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«, was bedeutet, dass das Programm erfolgreich ausgeführt wurde, oder »1«, was bedeutet, dass 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 fehlschlug.
$ ls VerZeiCh && uname && find / -name Datei /bin/ls: VerZeiCh: No such file or directory
Listing 3.12 &&
Der ||-Operator
Das Gegenstück zum &&-Operator stellt der ||-Operator dar. Anders als von && werden die durch || aneinandergereihten Kommandos nur dann ausgeführt, wenn das vorherige fehlschlägt. Man verwendet diesen Operator besonders gerne zur Ausgabe von Fehlermeldungen und zum Ausführen von »Plan B«.
pgrep X >/dev/null || echo "use 'startx' to start X"
Listing 3.13 Beispielanwendung des ||-Operators
3.7.3 Mehrzeilige Kommandos
Oftmals ist es recht unübersichtlich und unangenehm, sehr lange Kommandoreihen oder lange Einzelkommandos als Befehl zu übergeben. Viel einfacher ist es hingegen, wenn man diese Kommandos und Kommandoreihen auf mehrere Zeilen verteilt.
Diese mehrzeiligen Kommandos werden mit einem Backslash (»\«) realisiert.
Im Folgenden übergeben wir find das zweite und dritte Element des Argumentvektors in einer neuen Zeile:
$ find /usr/local/share/doc/usd \ -name bc \ /usr/share/doc/usd/06.bc/bc
Listing 3.14 Ein Kommando über mehrere Zeilen
3.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 nun auch die Möglichkeit, shell-interne Kommandos auszuführen.
type
Je nach Shell sind verschiedene Kommandos in der Shell implementiert. In der bash ist beispielsweise ein eigenes kill-Kommando implementiert. 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 im Allgemeinen 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 <Auch andere Shells, etwa die Z-Shell, bieten diese Funktionalität.>). An type muss lediglich der Name eines Kommandos bzw. Programms als Parameter übergeben werden. Daraufhin gibt type entweder aus, dass es sich dabei um ein Shell-Builtin oder um ein Programm handelt, dessen absoluter Pfad dann ausgegeben wird.
$ type type type is a shell builtin $ type bash bash is /bin/bash
Listing 3.15 Verwendung von type
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.
$ type kill kill is a shell builtin $ ls /bin/kill
Listing 3.16 kill ist Programm und Builtin
/bin/kill
which
In der Grundfunktionalität gleich, jedoch dank einer Option etwas informativer, ist das Programm which.
which 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. <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 which (sofern $PATH entsprechend gesetzt ist) alle beiden Dateien.
$ which -a which which: shell built-in command /usr/bin/which
Listing 3.17 which
Alias?
In der Shell kann ein sogenannter »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 solcher Alias ist.
$ 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
Listing 3.18 Alias-Überprüfung
3.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.
$ alias cl="cd ..;ls" cll="cd ..;ll" ll="ls -alhoF" ls="/bin/ls -aF"
Listing 3.19 Aktuelle Alias-Liste anzeigen
Der Vorteil liegt klar auf der Hand: Wenn Sie beispielsweise ständig das Kommando ls -laFh ausführen und sich dafür den Alias ll erstellen, sparen Sie Zeit und vertippen sich dabei nur sehr unwahrscheinlich.
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.
$ ll ../eil2/buch.ps -rw------- 1 sw sw 37.7M Feb 20 13:55 ../eil2/buch.ps
Listing 3.20 ll
Einen Alias erstellen und modifizieren
Einen 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 einen Alias, um den SSH- Login auf einem Host zu automatisieren:
$ alias ssh_milk='export TERM=xterm; > ssh swendzel@192.168.0.2'
Listing 3.21 Alias verwenden
Ein Alias kann modifiziert werden, indem ihm einfach erneut ein (anderer) Befehl zugewiesen wird.
Einen Alias löschen
Manchmal möchte man (warum auch immer) einen erstellten Alias löschen. Dies wird ganz einfach dadurch bewerkstelligt, dass man dem Kommando unalias den entsprechenden Namen des Alias übergibt.
$ alias system="uname -sr" $ system OpenBSD 3.6 $ unalias system $ system zsh: command not found: system
Listing 3.22 unalias
3.7.6 Verzeichniswechsel
Im letzten Kapitel haben Sie bereits die wichtigsten Grundlagen gelernt, um sich frei durch den Verzeichnisbaum zu arbeiten, sprich Verzeichnisse zu wechseln (cd), das aktuelle Arbeitsverzeichnis auszugeben (pwd) und den Inhalt von Verzeichnissen auszugeben (ls).
Nun wollen wir uns einmal 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 (zumindest grob) aus dem vorherigen Kapitel – sie sind 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 <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.
$ pwd /home/user $ cd . $ pwd /home/user $ ./script.sh ...
Listing 3.23 Ein Skript im aktuellen Verzeichnis ausführen
» .. «}
Verwenden Sie hingegen zwei Punkte, 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 durch Slashes auch aneinandergereiht werden.
$ pwd /usr/local/bin $ cd ../../include $ pwd /usr/include
Listing 3.24 ..
» ~- «}
Geben Sie diese 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:
$ pwd /usr/local/bin $ cd /etc $ pwd /etc $ cd ~- $ pwd /usr/local/bin
Listing 3.25 Ins voherige Verzeichnis zurückkehren
»~«
Gibt man für den Verzeichniswechsel eine Tilde (~) an, so wechselt man in sein 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. <Dazu muss sowohl das Lese- als auch das Ausführrecht gegeben sein, also r-x.>
$HOME und » «
Wechselt man mit der Variable $HOME das Verzeichnis, so kommt man – Sie werden es bereits ahnen – ebenfalls in sein Heimatverzeichnis. Die Verwendung der $HOME-Variable ist allerdings nur möglich, sofern diese auch (korrekt) gesetzt ist, was bis auf einige Ausnahmesituationen immer der Fall sein sollte.
Derselbe Wechsel in das Heimatverzeichnis kann bewerkstelligt werden, indem man dem cd-Kommando einfach gar keinen Parameter übergibt.
$ pwd /etc $ cd $HOME; pwd /home/user $ cd /etc; cd; pwd /home/user
Listing 3.26 Trautes Heim
3.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 vom echo-Programm bzw. -Kommando. Dieses Kommando gibt den ihm übergebenen Text auf der Konsole aus und ist besonders in der Shellskriptprogrammierung, etwa zum Einsehen von Variablenwerten, äußerst nützlich.
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 echo gibt ihn aus.
$ echo "Hallo, Welt !" Hallo, Welt!
Listing 3.27 echo
Wie Ihnen vielleicht aufgefallen ist, gibt es doch etwas zu beachten: Einige Sonderzeichen, wie im obigen Beispiel das Ausrufezeichen, müssen durch Escape-Sequenzen eingeleitet werden, da selbige 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 solcherlei Probleme durch Hochkommas umgehen. Alles, was Sie in Hochkommas stellen, wird von der Shell nicht weiter interpretiert, echo gibt es dann einfach aus.
$ echo 'Hallo, Welt!' Hallo, Welt!
Listing 3.28 echo in Verwendung mit Hochkommas
3.7.8 Shell-Variablen
Ein wichtiges Werkzeug im Umgang mit der Shell, insbesondere bei der Shellskriptprogrammierung, sind Variablen.
Einer Variable können Sie einen Wert zuweisen, auf den Sie später wieder (und beliebig oft) zugreifen können.
Solch ein Wert, den Sie einer Variable zuweisen, kann eine Zahl, die Ausgabe eines ganzen Programms oder ein String, also eine Zeichenkette, wie etwa »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, soll in einer Variable gespeichert werden. Es wäre beispielsweise sinnvoll, dieser Variable den Namen »KATZE« oder »KATZENNAME« zu geben. In der Regel schreibt man Shell-Variablen übrigens groß, dies ist jedoch nicht zwingend notwendig!
Die Zuweisung erfolgt in der Familie der Bourne-Shell <In der Familie der C-Shell muss hierzu das Shell-Builtin set verwendet werden.> durch ein Gleichheitszeichen:
$ KATZE=Felix
Listing 3.29 Der Variable »KATZE« den Wert »Felix« zuweisen
Durch eine erneute Zuweisung eines Wertes wird der alte Variablenwert überschrieben.
Abfrage von Werten
Um den Wert einer Variablen einzusehen, kann unter anderem das echo- Programm verwendet werden. Die Shell übergibt dem echo-Programm in diesem Fall den Inhalt der angegebenen Variablen, d. h., dass das echo-Programm nicht mitbekommt, dass es den Inhalt einer Variablen ausgibt. Die beiden folgenden Befehle bewirken folglich das Gleiche:
$ echo Felix Felix $ echo $KATZE Felix
Listing 3.30 echo mit bzw. ohne Variable
Beachten Sie, dass beim Zugriff auf eine Variable ein Dollarzeichen ($) vor ihrem Namen gesetzt werden muss, sonst interpretiert die Shell den Variablennamen als String:
$ echo KATZE KATZE
Listing 3.31 Fehler: Dollarzeichen vergessen
Löschen von Variablen
Um eine Variable wieder zu löschen, muss deren Name nur dem unset-Kommando übergeben werden.
$ echo $KATZE Felix $ unset KATZE $ echo $KATZE $
Listing 3.32 unset
Variablen in Text einbetten und ausgeben
Um eine Variable in den Text einer Ausgabe (oder einer anderen Variable) 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.
$ echo "Herzlich willkommen, $KATZE !" Herzlich willkommen, Felix!
Listing 3.33 Variable im Text
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 eben besprochene Variante verwenden, sondern müssen die Variable in geschweifte Klammern setzen.
Das ist nötig, um Anfang und Ende des Variablennamens genau zu markieren.
$ KATZE2="Mauzi" $ echo "Herzlich willkommen $KATZE2 !" Herzlich willkommen, Mauzi $ echo "Herzlich willkommen, ${KATZE}2 !" Herzlich willkommen, Felix2!
Listing 3.34 Variable im Text
Mehr zu der Einbettung von Variablen in Text oder in andere Variablenwerte erfahren Sie im Abschnitt »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). <In einigen Shells gibt set noch zusätzliche Informationen, etwa Shellfunktionen, aus.>
$ set ... XCURSOR_SIZE="" XCURSOR_THEME="" XYRIA=/home/swendzel/projekte/xyria_ ZSH_NAME=zsh ZSH_VERSION=4.2.1 _=set aliases ...
Listing 3.35 set, ausgeführt in der Z-Shell
Variablen einlesen
Selbstverständlich kann man auch den Wert einer Variable von der Tastatur einlesen lassen. Dies wird über das shell-interne Kommando read bewerkstelligt. Man übergibt read den Namen der gewünschten Variable, lässt allerdings (wie bei jeder Zuweisung) das Dollarzeichen davor weg. Die Eingabe wird durch die Eingabetaste beendet.
$ read Name Felix $ echo $Name Felix
Listing 3.36 read verwenden
Schreibgeschützte Variablen
Variablen können mit einem Schreibschutz versehen werden. Damit kann sichergestellt werden, dass ihr Wert nicht aus Versehen wieder verändert wird. Hierzu wird dem readonly-Kommando einfach der Name der jeweiligen Variable übergeben. Übergibt man readonly keinen Parameter, so bekommen 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 beiden Variablenarten vorenthalten.
Eine globale Variable wird nämlich, 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:
IRCNAME="Steffen W" IRCNICK=cdp_xe IRCPORT=6667 IRCSERVER=milk.sun
Listing 3.37 Globale Variablen für BitchX
Würden Sie nun das Programm bitchx aus einer Shell mit diesen globalen Variablen starten, würde bitchx diese 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 dieses Kommando export übergeben.
$ export KATZE=Felix $ export | grep KATZE KATZE=Felix
Listing 3.38 Erzeugen einer globalen Variable
Auch globale Variablen können mit dem Kommando unset wieder gelöscht werden.
Die wichtigsten globalen Variablen
Es gibt ein paar globale Variablen, die für die Nutzung des Unix-Betriebssystems äußerst wichtig sind und daher bekannt sein sollten. Wir haben diese sowie ihre Bedeutung in einer kleinen Tabelle zusammengefasst.
Einige spezielle Variablen 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 |
Diese Variable enthält eine Liste von Verzeichnissen, die nach einer relativ angegebenen, ausführbaren Datei durchsucht werden sollen. |
$PS1 bis $PS4 |
Kommandozeilenprompt |
$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« |
$# |
Gesamtanzahl der an eine Funktion oder ein Skript übergebene Parameter |
$? |
Rückgabewert des zuletzt in dieser Shell beendeten Prozesses |
$* und $@ |
Alle dem Skript oder einer Funktion übergebenen Parameter |
$! |
Prozess-ID des letzten Hintergrundprozesses |
Der Shell-Prompt
Eine Shell verfügt über einen »Standard-Prompt« und einige »Neben-Prompts«. Doch was ist eigentlich solch ein Prompt? Im Prinzip ist ein Prompt die Ausgabe von Textzeichen, die Sie zur Eingabe eines Kommandos auffordert.
Je nach der Shell, die Sie verwenden, und der persönlichen Konfiguration der entsprechenden Variablen kann solch ein Prompt völlig unterschiedlich aussehen. Hier im Buch haben wir meistens »user$« und
$ als Benutzer-Prompt, sowie »root#« und »#« als Superuser-Prompt 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 mit
$ unset PS1
zu löschen – Sie werden feststellen, dass nun jegliche Eingabeaufforderung fehlt. Sie können allerdings nach wie vor Befehle ausführen. Um wieder einen Prompt herzustellen, können Sie die Variable PS1 wieder global setzen – welch passende Übung zum obigen Unterabschnitt. <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), der durch einen ihm 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 |
Sequenz | Wirkung |
\n |
Neue Zeile (Prompts können tatsächlich über mehrere Zeilen verteilt werden.) |
\r |
Carriage-Return |
\s |
Der Name der Shell |
\t |
Zeit im 24-Stunden-Format |
\T |
Zeit im 12-Stunden-Format |
\@ |
Zeit im AM/PM-Format |
\u |
Der Name des Benutzers |
\v |
Die Version der bash |
\V |
Wie \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, 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 eine große Anzahl der Benutzer verwenden die
»Benutzer@Host Verzeichnis$«-Variante, die ein an dieser Stelle sehr gut passendes Beispiel zur Nutzung der Escape-Sequenzen darstellt.
user$ PS1="\u@\h \w\$" swendzel@deb-sid /usr$ ls …
Listing 3.39 Setzung des bash-Prompts mit Escape-Sequenzen
Weitere Prompts
Neben dem Standard-Prompt $PS1 gibt es noch weitere Prompts:
$PS2..4
Zum einen sind dies die Eingabeaufforderungen zur Vervollständigung von Shell-Anweisungen (hiermit sind beispielsweise if-Anweisungen gemeint, die Sie in der Shellskriptprogrammierung kennenlernen werden).
Sie werden mit $PS2 ... $PS4 (je nach Shell) bezeichnet. Diese werden allerdings fast nie geändert werden, da es recht wenig Sinn macht, sie zu ändern, und ihre Standardkonfiguration ausreicht.
$RPS1
Zum anderen ist dies zumindest in der Z-Shell der $RPS1-Prompt. Dieser Prompt ist ein rechtsseitiger Prompt, den man beispielsweise sehr gut nutzen kann, um sich Uhrzeit und Datum ausgeben zu lassen.
3.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 ganz bestimmte Einbettungszeichen verwendet, nämlich die sogenannten Backticks <Auf einer PC-Tastatur drückt man für diese Zeichen Shift und ' (das ist die Taste neben ?/ß)>. Alles, was Sie innerhalb dieser Zeichen schreiben, wird von der Shell als Befehl interpretiert. Die Ausgabe des Befehls 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 Variable $OUTPUT die Ausgaben des ls-Befehls zu.
user$ OUTPUT=`ls` user$ echo $OUTPUT CVS Makefile TODO ZEITPLAN anhg_komref.tex buch.dvi buch.idx buch.ilg buch.ind ...
Listing 3.40 Kommandosubstitution
Wie Sie sehen, kann die Variable sofort weiterverwendet werden, indem man sie wie im Beispiel einem Programm wie echo übergibt. Vielleicht fragen Sie sich ja bereits, ob man nicht auch direkt eine Kommandosubstitution ohne eine 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 Kommandoreferenz) soll uns Detailinformationen zu den einzelnen Dateien des Verzeichnisses ausgeben. Diese Dateien übergeben wir jedoch über eine Kommandosubstitution.
Dies ist nicht sonderlich sinnvoll, verdeutlicht aber sehr gut die Funktionsweise der direkten 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 anhg_komref.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 ...
Listing 3.41 Direkte Kommandosubstitution
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 Kommandosubstitition 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!
... und nun noch einige Details
Diese Kommandosubstitution ist leider nicht immer so 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 Hochkommas, Backticks und Anführungszeichen. Jede dieser drei Möglichkeiten hat andere Folgen. Nehmen wir einmal an, der Variablen $VAR wurde der Text »hallo« zugewiesen ...
Anführungs- zeichen
In Anführungszeichen werden sowohl Variablenwerte als auch Kommandosubstitutionen umgesetzt.
$ echo "$VAR `pwd`" hallo /home/cdp_xe/books/kompendium
Listing 3.42 Anführungszeichen
Backticks
In Backticks werden Kommandosubstitutionen eingeschlossen. Variablenwerte werden hierbei als Kommando interpretiert.
$ echo `$VAR` `pwd` zsh: command not found: hallo /home/cdp_xe/books/kompendium
Listing 3.43 Backticks
Hochkommata
In Hochkommata sind sowohl Variablenangaben als auch explizit in Backticks angegebene Kommandosubstitutionen wirkungslos.
$ echo '$VAR `pwd`' $VAR `pwd`
Listing 3.44 Hochkommata