|
|
(162 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
Zeile 1: |
Zeile 1: |
| | '''Builtins''' - Kommandos, die von der Shell bereitgestellt werden |
|
| |
|
| = Beschreibung = | | == Beschreibung == |
| Es liegt wohl in der Natur des Linux-Neulings, seine Testprogramme und -skripten «"test« zu benennen (eigentlich kann ich mich an keinen Linuxkurs erinnern, indem nicht mindestens einer der Teilnehmer auf diese Weise mit den builtin Kommandos der Bash konfrontiert wurde).
| | ; Kommandos, die von der Shell bereitgestellt werden |
| | * Eingebaute Befehle (Builtins) |
| | * Kein eigener Prozess |
| | * Von der Shell interpretiert und ausgeführt |
|
| |
|
| Nach verrichteter Arbeit zeigte der Testlauf:
| | ; Intern/Extern |
| '''ls -l test'''
| | Manchmal gibt es eine eingebaute und eine externe Version |
| -rwxr-xr-x 1 user users 12177 Sep 23 10:52 test
| | 'echo' (intern) und '/bin/echo' (extern) |
| '''test''' | |
|
| |
|
| Mit Kenntnis des Vorgehens der Bash bei der Suche nach einem Kommando, gelangt man bald zum Schluss, dass sich ein builtin Kommando vorgedrängelt hat.
| | === Gründe für eingebauten Befehlen === |
| | # Befehl nicht als Unix-Kommando verfügbar |
| | #* Beispielsweise ''source'' |
| | # Weil ein builtin Kommando effizienter arbeitet |
| | #* als ein externes Kommando (keine Prozesserzeugung notwendig; Beispiel »echo«) |
| | # Weil nur ein eingebautes Kommando Bash-interne Variablen ändern kann (Beispiel »export«) |
| | # Weil ein Kommando wie »exec« nur innerhalb der Bash realisierbar ist |
|
| |
|
| Es gibt eine Fülle solcher eingebauter Kommandos und mindestens 4 Gründe, warum solche in der Bash überhaupt existieren: # Weil es ein solches Kommando in Unix nicht gibt (Beispiel "source")
| | === Arten von builtin === |
| # Weil ein builtin Kommando effizienter arbeitet, als ein externes Kommando (keine Prozesserzeugung notwendig; Beispiel »echo«)
| |
| # Weil nur ein eingebautes Kommando Bash-interne Variablen ändern kann (Beispiel »export«)
| |
| # Weil ein Kommando wie »exec« nur innerhalb der Bash realisierbar ist
| |
|
| |
|
| Betrachten wir die einzelnen builtin-Kommandos:
| | === Was wird gestartet? === |
| * Etliche der besprochenen Shell-Kommandos starten nicht, wie sonst üblich, einen eigenen Prozeß, sondern sie werden direkt von der Shell interpretiert und ausgeführt. | | * [[type]] |
| * Teilweise ist keine E/A-Umleitung möglich. Etliche Kommandos der folgenden Auswahl wurden schon besprochen. | | * [[whereis]] |
| * Andere werden weiter unten behandelt. Zum Teil gibt es interne und externe Versionen, z. B. 'echo' (intern) und '/bin/echo' (extern).
| |
|
| |
|
| {|
| | === Builtins ein- und ausschalten === |
| |-
| |
| | | '''break'''
| |
| | | Schleife verlassen
| |
| |-
| |
| | | '''continue'''
| |
| | | Sprung zum Schleifenanfang
| |
| |-
| |
| | | '''echo'''
| |
| | | Ausgabe
| |
| |-
| |
| | | '''eval'''
| |
| | | Mehrstufige Ersetzung
| |
| |-
| |
| | | '''exec'''
| |
| | | Überlagerung der Shell durch ein Kommando
| |
| |-
| |
| | | '''exit'''
| |
| | | Shell beenden
| |
| |-
| |
| | | '''export'''
| |
| | | Variablen für Subshells bekannt machen
| |
| |-
| |
| | | '''read'''
| |
| | | Einlesen einer Variablen
| |
| |-
| |
| | | '''shift'''
| |
| | | Parameterliste verschieben
| |
| |-
| |
| | | '''trap'''
| |
| | | Behandlung von Signalen
| |
|
| |
|
| | == Übersicht == |
| | {| class="wikitable sortable" |
| |- | | |- |
| |}
| | ! Befehl !! Beschreibung |
| | |
| = Null - Kommando : =
| |
| Dieses »Kommando« tut nichts, außer einen Rückgabewert »0« zu erzeugen (»0« ist der übliche Rückgabewert eines Kommandos unter Unix, wenn seine Ausführung erfolgreich war).
| |
| | |
| Nützlich ist es in Shellskripten, falls Sie in Bedingungen einen wahren Wert (»true«) benötigen oder an Positionen, wo syntaktisch ein Kommando erwartet wird, Sie aber keines benötigen:
| |
| | |
| $ '''while : ;do echo "Eine Endlosschleife"; done'''
| |
| Eine Endlosschleife
| |
| Eine Endlosschleife
| |
| Eine Endlosschleife
| |
| ...
| |
| Eine Endlosschleife[Strg]+[C]
| |
| '''if test -a foo ; then :; else echo "Datei nicht existent"; fi'''
| |
| Datei nicht existent
| |
| | |
| = source =
| |
| Die angegebene Datei wird gelesen und innerhalb der Shellumgebung ausgeführt.
| |
| | |
| Ist die Datei ohne Pfad angegeben, wird dabei in Verzeichnissen der PATH-Variable gesucht.
| |
| | |
| Wird sie dort nicht gefunden, wird das aktuelle Verzeichnis betrachtet. Das Kommando kann sich der C-Programmierer als "include" der Bash vorstellen.
| |
| | |
| Manche Linuxdistributionen (bspw. RedHat) verwenden dieses Kommando in ihren Runlevel-Skripten, um eine Funktionsbibliothek einzubinden.
| |
| | |
| Auf der Kommandozeile bietet sich "source" an, um die initiale Umgebung zu rekonstruieren (weil man u.U. die Umgebungsvariablen "verbogen" hat):
| |
| | |
| $ '''source /etc/profile'''
| |
| # bzw.
| |
| '''. /etc/profile'''
| |
| | |
| = alias =
| |
| Dient der Definition einer Abkürzung für ein(e) Kommando(folge). Mit der Option -p werden alle vorhandenen Aliasse aufgelistet; Beispiele wurden bereits im einleitenden Abschnitt zu Bash (Eingabehilfen) und in Allgemeines zu Shells genannt.
| |
| | |
| = jobs =
| |
| Listet die Jobnummern aller Hintergrundprozesse auf.
| |
| | |
| = bind =
| |
| Das Kommando besitzt in erster Linie im Zusammenspiel mit der Datei /etc/inputrc (bzw. ~/.inputrc) eine Rolle. Besagte Dateien enthalten die »Keybindings«, also die Zuordnungen von Tastenkombinationen zu bestimmten Funktionalitäten.
| |
| | |
| Wenn bspw. die unter Interaktive Bash aufgeführten Eingabehilfen bei Ihnen nicht funktionieren sollten, dann fehlt in der Konfiguration Ihrer Bash die notwendige Zuordnung (oder Sie verwenden eine ältere Bashversion).
| |
| | |
| bind kann auch interaktiv benutzt werden, um bestimmte Keybindings zu löschen, um sie sich anzeigen zu lassen oder neue zu definieren.
| |
| | |
| Letzteres ermöglicht gar die Ausführung von Kommandos bei Betätigung einer zuvor definierten Tastensequenz. Benötigen Sie solche Sequenzen häufig, so nehmen Sie sie in ihre persönliche ~/.inputrc auf.
| |
| | |
| Wenn Sie mit der Bash einigermaßen per Du sind, so kennen
| |
| | |
| Sie die eine oder andere Tastenkombination, um geschwind auf der Kommandozeile zu navigieren oder diese zu manipulieren. Hinter den Mechanismen verbergen sich readline-Funktionen.
| |
| | |
| Welche es gibt, verrät der Aufruf »bind -l« und über deren aktuelle Belegung weiß »bind -p« bescheid. Erscheint in letzter Ausgabe »not bound«, so ist diese Funktion nicht belegt.
| |
| | |
| $ '''bind -p | head -5'''
| |
| "\C-g": abort
| |
| "\C-x\C-g": abort
| |
| "\e\C-g": abort
| |
| "\C-j": accept-line
| |
| | |
| Angenommen Sie verfassen im vi ein deutschsprachiges html-Dokument.
| |
| | |
| Um die Zeichen »ä«, »ö«,... in Browsern, die deutsche Zeichensätze nicht unterstützen, korrekt darzustellen, sollten alle länderspezifischen Zeichen im Unicode dargestellt werden, also bspw. »ü« anstatt »ü«.
| |
| | |
| Die komfortable Lösung ist das Verändern der Tastaturbelegung, so dass automatisch der Unicode im Text erscheint. In der Bash erreichen Sie dies wie folgt:
| |
| '''bind '"ü":"ü"' '''
| |
| | |
| Sobald Sie »ü« tippen, erscheint in der Eingabe »ü«. Um die Bindung aufzuheben, geben sie »bind -r <Tastensequenz>« an; aber für gewöhnlich besteht der Wunsch, die alte Belegung wieder herzustellen.
| |
| | |
| Eine Taste, die »als sie selbst« definiert wird, wird in folgender Manier belegt:
| |
| '''bind 'ü:self-insert' '''
| |
| | |
| Obige Form der Tastenbindung nennt man auch Makro; daneben können sie auch Funktionen und gar Kommando(s) an Tasten(sequenzen) binden.
| |
| | |
| Das nachfolgende Beispiel bindet [Strg]+[b] an die Ausgabe des Kalenders des aktuellen Monats:
| |
| | |
| '''bind -x '"\C-b":cal'
| |
| [Strg]+[B]'''
| |
| November 2000
| |
| So Mo Di Mi Do Fr Sa
| |
| 1 2 3 4
| |
| 5 6 7 8 9 10 11
| |
| 12 13 14 15 16 17 18
| |
| 19 20 21 22 23 24 25
| |
| 26 27 28 29 30
| |
| | |
| Ihre gesammelten Werke der Tastenbindungen können Sie auch in eine beliebige Datei schreiben und diese mittels "bind -f <Datei>" laden.
| |
| | |
| = break [n] =
| |
| Dient zum expliziten Verlassen einer Schleife.
| |
| | |
| Ohne Angabe eines Arguments wird die unmittelbar umgebende Schleife verlassen; möchte man tiefere Verschachtelungen verlassen, muss die Tiefe angegeben werden:
| |
| ...
| |
| while [ Bedingung ]; do
| |
| for i in Liste; do
| |
| case "$i" in
| |
| foo*) break;
| |
| bla*) tue etwas ;;
| |
| *) Fehler; break 2;
| |
| esac
| |
| done
| |
| done
| |
| ...
| |
| | |
| = break =
| |
| Die Syntax der break-Anweisung lautet wie folgt:
| |
| break [ n ]
| |
| | |
| Mit break kann man die innerste Ebene (bzw. n Schleifenebenen) verlassen ohne den Rest der Schleife auszuführen.
| |
| | |
| = builtin Kommando =
| |
| Bei der Suche nach Kommandos betrachtet die Shell Aliasse und Funktionen noch vor den eingebauten Kommandos. Überdeckt nun ein solcher Name ein builtin-Kommando, so wird beim einfachen Aufruf immer der Alias bzw. die Funktion ausgeführt werden.
| |
| | |
| Mit vorangestelltem builtin weist man nun die Bash an, auf jeden Fall ihr eingebautes Kommando aufzurufen.
| |
| | |
| Der Rückgabestatus ist gleich dem Rückgabewert des Builtin's oder "falsch", falls das Kommando kein builtin ist.
| |
| | |
| = cd =
| |
| Wechsel des Verzeichnisses
| |
| | |
| = command =
| |
| Ein weiterer Weg, um die Verwendung von Aliassen oder Funktionen bei der Suche nach einem Kommando temporär auszuschalten, ist ein dem zu startenden Kommandonamen voranzustellendes command.
| |
| | |
| Die Shell sucht nun einzig in der Liste der eingebauten Kommandos und den Pfaden aus PATH.
| |
| | |
| Hilfreich ist die Option -p, falls die PATH-Variable einmal "völlig daneben" belegt ist; die Bash sucht in default-Pfaden und findet so zumindest die wichtigsten Programme.
| |
| | |
| = compgen =
| |
| Mit dem Kommando lassen sich die möglichen Expansionen anzeigen. Um bspw. gezielt die denkbaren Erweiterungen aller mit "l" beginnenden Aliasse zu erhalten, ist folgende Kommandozeile notwendig:
| |
| | |
| $ '''compgen -A alias l'''
| |
| l
| |
| la
| |
| ll
| |
| ls
| |
| ls-l
| |
| | |
| Anstatt von "alias" können u.a. Funktionen ("function"), Schlüsselworte der Bash ("keywords"), Dateinamen ("file"), Verzeichnisse ("directory"), Variablen ("variable") expandiert werden. Noch weit reichender sind die Möglichkeiten in Bezug auf Dateinamen, da hier mit Suchmustern gearbeitet werden kann:
| |
| | |
| $ '''compgen -G '*c*''''
| |
| Packages
| |
| bla.xcf
| |
| countdir
| |
| linuxbuch
| |
| Documents
| |
| | |
| Abgesehen von -r und -r verwendet compgen dieselben Optionen wie das nachfolgend beschriebene complete.
| |
| | |
| = complete =
| |
| Mit diesem Kommando kann das ganze Verhalten der Bash bei der Vervollständigung von Argumenten verändert werden.
| |
| | |
| Bevor wir uns mit den Optionen auseinander setzen, soll ein Beispiel die Mächtigkeit des Konzepts andeuten.
| |
| | |
| '''Beispiel'''
| |
| | |
| Als Argumente für das Programm xv (dient der Anzeige von Dateien diverser Grafikformate) sollen bei der automatischen Dateinamensergänzung nur Dateien mit einer typischen Dateiendung (*.jpg, *.gif,...) berücksichtigt werden. Mit complete müsste die Bash wie folgt eingerichtet werden:
| |
| | |
| # Die Option "extglob" (vergleiche shopt) muss gesetzt sein:
| |
| '''shopt -q extglob || shopt -s extglob'''
| |
|
| |
| # Test des bisherigen Verhaltens:
| |
| '''xv s[Tab][Tab]'''
| |
| sax_0.gif sax_norm.tmp sax_xxx.jpg
| |
| sax_grob.tmp sax_post.tmp start_taper
| |
|
| |
| '''complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' xv'''
| |
| # Test des jetzigen Verhaltens:
| |
| '''xv s[Tab][Tab]'''
| |
| sax_0.gif sax_xxx.jpg
| |
| | |
| Mit der Option -p lässt sich jede Spezifikation anzeigen und mit -r auch wieder löschen. Wird kein Name angegeben, betrifft die Aktion jede Spezifikation:
| |
| | |
| '''complete -p'''
| |
| complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' xv
| |
| '''complete -r xv'''
| |
| | |
| complete wurde im Beispiel durch die Option -f angewiesen, den folgenden Ausdruck einer Dateinamenserweiterung zu unterziehen. Alternative Expansionen sind (Auswahl):
| |
| | |
| {|
| |
| |- | | |- |
| | | '''-a ''' | | | [[Null]] || |
| | colspan="2" | Es wird eine Expansion zu einem bekannten Aliasnamen versucht | |
| |- | | |- |
| | | '''-b ''' | | | [[source]] || |
| | colspan="2" | Erweiterung zu einem eingebauten Kommando | |
| |- | | |- |
| | | '''-c ''' | | | [[alias]] || Definition einer Abkürzung für ein Kommando |
| | colspan="2" | Erweiterung zu einem Kommando | |
| |- | | |- |
| | | '''-e ''' | | | [[jobs]] || Listet die Jobnummern aller Hintergrundprozesse auf |
| | colspan="2" | Exportierte Variable | |
| | |
| Als Beispiel definieren wir eine Funktion, die den Inhalt einer exportierten Variablen anzeigen soll:
| |
| | |
| show_exports() { echo $*; }
| |
| | |
| Beim Aufruf dieser Funktion sollen bei versuchter Expansion alle möglichen Erweiterungen angezeigt werden. Um sich den Inhalt der Variablen selbst anzuschauen, muss dieser ein Dollarzeichen voranstehen. Mit der Option -P lässt sich ein solches Präfix für ein Expansionsergebnis festlegen.
| |
| | |
| Die complete-Zeile sollte wie folgt aussehen:
| |
| | |
| '''complete -e -P '$''''
| |
| # Test
| |
| '''show_exports PO[Tab]
| |
| show_exports $POVRAYOPT'''
| |
| -l/usr/lib/povray/include
| |
| | |
| |- | | |- |
| | | '''-f ''' | | | [[bind]] || |
| | colspan="2" | Dateinamenserweiterung | |
| |- | | |- |
| | | '''-u ''' | | | [[break]] || |
| | colspan="2" | Benutzernamen | |
| | |
| Als Beispiel soll das Kommando mail mit einem Benutzernamen expandiert werden. Als Suffix wird automatisch "@outside.all" ergänzt:
| |
| | |
| '''complete -u -S '@outside.all' mail'''
| |
| # Test
| |
| '''mail a[Tab]
| |
| mail alf@outside.all'''
| |
| |- | | |- |
| | | '''-v''' | | | [[cd]] || Verzeichnis wechseln |
| | colspan="2" | Variablennamen | |
| | |
| Als weitere Optionen stehen zur Verfügung:
| |
| |- | | |- |
| | | | | | [[command]] || |
| | | '''-G Muster''' | |
| | | Es wird eine Dateinamenserweiterung mit dem Muster versucht
| |
| |- | | |- |
| | | | | | [[compgen]] || |
| | | '''-C Kommando''' | |
| | | Das Kommando wird in einer Subshell gestartet und dessen Ausgabe als mögliche Vervollständigung eingesetzt
| |
| |- | | |- |
| | | | | | [[complete]] || Verhalten der Bash bei der Vervollständigung steuern |
| | | '''-X Muster''' | |
| | | Es wird eine Dateinamenserweiterung nach Ausführung aller anderen Optionen versucht. Alle Dateinamen, die mit dem Muster übereinstimmen, werden aus der Liste der möglichen Vervollständigungen entfernt
| |
| |- | | |- |
| | | | | | [[continue]] || |
| | | '''-P Präfix''' | |
| | | Nach Ausführung aller anderen Optionen werden die möglichen Erweiterungen mit dem angegebenen Präfix versehen
| |
| |- | | |- |
| | | | | | [[declare]] || Deklarieren von Variablen |
| | | '''-S Suffix''' | |
| | | Nach Ausführung aller anderen Optionen werden die möglichen Erweiterungen mit dem angegebenen Suffix versehen
| |
| | |
| |- | | |- |
| |} | | | [[dirs]] || Anzeige des Verzeichnisstacks |
| | |
| = continue =
| |
| Die Syntax der continue-Anweisung lautet wie folgt:
| |
| continue [ n ]
| |
| | |
| Man benutzt continue um die restlichen Befehle in einer Schleife zu überspringen und mit dem nächsten Schleifendurchlauf anzufangen.
| |
| | |
| Wenn der Parameter n angegeben wird, werden n Schleifenebenen übersprungen.
| |
| '''continue [n] '''
| |
| | |
| Dieses Kommando kann innerhalb von Schleifen verwendet werden, um unmittelbar mit dem nächsten Schleifendurchlauf fortzufahren.
| |
| | |
| Ohne Angabe von "n" ist die umgebende Schleife gemeint; mit Angabe einer ganzen Zahl "n" kann im Falle von verschachtelten Schleifen diejenige benannt werden, die zu durchlaufen ist
| |
| | |
| for i in $(ls); do
| |
| test -d $i && continue
| |
| # tue etwas...
| |
| done
| |
| | |
| = declare =
| |
| Zum Deklarieren von Variablen, wobei diese gleichzeitig mit Attributen versehen werden können; siehe unter Variablen
| |
| | |
| = dirs =
| |
| Dient zur Anzeige des Verzeichnisstacks. in Verzeichnis kann neben dem bekannten Kommando cd auch mit dem eingebauten Kommandos pushd bzw. popd gewechselt werden.
| |
| | |
| Bei letzterem Vorgehen wird das Verzeichnis auf einem Stack abgelegt, dessen Einträge popd in umgekehrter Reihenfolge entfernt und in das jeweilige Ausgangsverzeichnis wechselt.
| |
| | |
| = disown [Jobnummer(n)] =
| |
| Das Kommando ist die bash-eigene Realisierung des Kommandos nohup und ermöglicht, Jobs nachträglich vom Elternprozess (also die Shell) zu lösen.
| |
| | |
| D.h. bei Beendigung der Shell erhalten diese Prozesse kein Signal SIGHUP, sodass sie weiterhin existieren. Gleichzeitig werden die Jobs aus der Jobtabelle entfernt, sodass sie bspw. vom Kommando jobs nicht mehr berücksichtigt werden können.
| |
| | |
| Die Option -h schützt einen Prozess vor SIGHUP ohne ihn aus der Jobtabelle zu verbannen. Mit -a kann disown auf alle Jobs und mit -r auf alle laufenden (Status "Running") Jobs ausgedehnt werden.
| |
| | |
| = echo - Eine Zeile Text anzeigen =
| |
| echo [OPTION]... [ZEICHENKETTE]...
| |
| | |
| Gib ZEICHENKETTE(n) auf Standardausgabe aus.
| |
| | |
| '''Optionen'''
| |
| | |
| {|
| |
| |- | | |- |
| | | '''-n''' | | | [[disown]] || |
| | | gib keinen Zeilenvorschub am Ende der Zeile aus | |
| |- | | |- |
| | | '''-e''' | | | [[echo]] || Eine Zeile Text anzeigen |
| | | ermögliche Interpretation der \-Notationen unten | |
| |- | | |- |
| | | '''-E''' | | | [[enable]] || Eingebauten Kommandos der Shell aktivieren |
| | | verhindere Interpolation einiger Sequenzen in ZKETTEn | |
| |- | | |- |
| | | '''--help''' | | | [[eval]] || Liest seine Argumente, wobei die üblichen Ersetzungen stattfinden, und führt die resultierende Zeichenkette als Kommando aus. |
| | | gib diese Hilfe aus und beende das Programm | |
| |- | | |- |
| | | '''--version''' | | | [[exec]] || Das Kommando besitzt zwei Bedeutungen. |
| | | gib Versionsinformation aus und beende das Programm | |
| |- | | |- |
| |} | | | [[exit]] || Beendet die Shell |
| | |
| Ohne -E werden die folgenden Sequenzen erkannt und berechnet
| |
| | |
| {|
| |
| |- | | |- |
| | | '''\NNN''' | | | [[export]] || Exportieren von Variablen |
| | | Zeichen mit dem ASCII Code (oktal) | |
| |- | | |- |
| | | '''\\''' | | | [[fc]] || Manipulation der History-Einträge |
| | | Rückschrägstrich | |
| |- | | |- |
| | | '''\a''' | | | [[fg]] || holt einen Hintergrundprozess in den Vordergrund |
| | | Alarm (BEL) | |
| |- | | |- |
| | | '''\b''' | | | [[getopts]] || |
| | | Zeichen zurück | |
| |- | | |- |
| | | '''\c''' | | | [[hash]] || |
| | | unterdrücke Zeilenvorschub am Ende | |
| |- | | |- |
| | | '''\f''' | | | [[help]] || Schreibt einen kurzen Hilfetext zu einem eingebauten Kommando aus. |
| | | Seitenvorschub | |
| |- | | |- |
| | | '''\n''' | | | [[history]] || Kommandozeilenspeicher anzeigen |
| | | Zeilenvorschub | |
| |- | | |- |
| | | '''\r''' | | | [[kill]] || Signale an Prozesse senden |
| | | Wagenrücklauf | |
| |- | | |- |
| | | '''\t''' | | | [[let]] || Für jedes Argument wird eine arithmetische Substitution versucht |
| | | horizontaler Tabulatorstopp | |
| |- | | |- |
| | | '''\v''' | | | [[local]] || Definition lokaler Variablen |
| | | vertikaler Tabulatorstopp | |
| |- | | |- |
| |} | | | [[logout]] || Beendet eine Login-Bash und meldet den Benutzer ab. In einer Nicht-Login-Bash wird eine Fehlermeldung ausgegeben. |
| | |
| '''echo '''
| |
| | |
| Gibt alle Argumente, getrennt durch ein Leerzeichen, und einen abschließenden Zeilenumbruch aus.
| |
| | |
| Die Option -n unterdrückt den Zeilenumbruch und -e erzwingt die Auswertung Escape-Sequenzen:
| |
| | |
| '''echo "\a"'''
| |
| \a
| |
| '''echo -n "\a"'''
| |
| \a'''echo -e "\a"'''
| |
| PIEP
| |
| | |
| Das nächste Beispiel verwendet "\b", um den Cursor um eine Position zurück zu bewegen:
| |
| | |
| '''cat ticker'''
| |
| #!/bin/sh
| |
|
| |
| declare -i zeit=0
| |
| echo -en "Sekunden: \t"
| |
|
| |
| while :; do
| |
| for ((i=${#zeit}; i; i--)); do
| |
| echo -en "\b"
| |
| done
| |
| echo -en $zeit
| |
| zeit=zeit+1
| |
| sleep 1
| |
| done
| |
| | |
| = enable =
| |
| Die eingebauten Kommandos der Shell lassen sich bei Bedarf aktivieren oder auch abschalten.
| |
| | |
| Letzteres kann nützlich sein, wenn Sie fortwährend auf ein externes Kommando zugreifen müssen, das denselben Namen wie ein Shell-Builtin besitzt.
| |
| | |
| Da die Shell immer ihr eigenes Kommando bevorzugt, müssten Sie ständig den vollständigen Pfad eintippen - auf die Dauer ein lästiges Unterfangen.
| |
| | |
| Mit -n <Kommando> deaktivieren Sie das Builtin; ohne Eingabe einer Option lässt es sich wieder aktivieren.
| |
| | |
| = eval =
| |
| Das Kommando eval liest seine Argumente, wobei die üblichen Ersetzungen stattfinden, und führt die resultierende Zeichenkette als Kommando aus.
| |
| | |
| Die Argumente der Kommandozeile werden von der Shell gelesen, wobei Variablen- und Kommandoersetzungen sowie Dateinamenersetzung durchgeführt werden.
| |
| | |
| Die sich ergebende Zeichenkette wird anschließend erneut von der Shell gelesen, wobei wiederum die oben genannten Ersetzungen durchgeführt werden. Schließlich wird das resultierende Kommando ausgeführt. Beispiel (Ausgaben fett):
| |
| | |
| $ A="Hello world!"
| |
| $ X='$A'
| |
| $ echo $X
| |
| '''$A'''
| |
| $ eval echo $X
| |
| '''Hello world!'''
| |
| | |
| Der Rückgabestatus von eval ist der Rückgabestatus des ausgeführten Kommandos oder 0, wenn keine Argumente angegeben wurden. Ein weiteres Beispiel:
| |
| | |
| $ cat /etc/passwd | wc -l
| |
| 76
| |
| $ foo='cat /etc/passwd'
| |
| $ bar=`| wc -l'
| |
| $ $foo $bar # Fehler: $bar ist Argument von cmdl
| |
| cat: | : No such file or directory
| |
| cat: wc: No such file or directory
| |
| cat: -l: No such file or directory
| |
| $ eval $foo $bar
| |
| 76
| |
| | |
| In diesem Beispiel wird zunächst ein einfaches Kommando gestartet, das die Anzahl der Zeilen der Datei /etc/passwd bestimmt.
| |
| | |
| Anschließend werden die beiden Teile des gesamten Kommandos in die zwei Shell-Variablen foo und bar aufgeteilt.
| |
| | |
| Der erste Aufrufversuch $foo $bar bringt nicht das gewünschte Ergebnis, sondern lediglich einige Fehlermeldungen, da in diesem Fall der Wert von bar als Argument für foo interpretiert wird ('cat' wird mit den Dateien '/etc/passwd', '|', 'wc' und '-l' aufgerufen).
| |
| | |
| Wird jedoch das Kommando eval auf die Argumente $foo und $bar angewendet, werden diese zunächst zur Zeichenkette "cat /etc/passwd | wc -l" ersetzt.
| |
| | |
| Diese Zeichenkette wird dann durch das Kommando eval erneut von der Shell gelesen, die jetzt das Zeichen "|" in der Kommandozeile als Pipesymbol erkennt und das Kommando ausführt.
| |
| | |
| Das Kommando eval wird üblicherweise dazu eingesetzt, eine Zeichenkette als Kommando zu interpretieren, wobei zweifach Ersetzungen in den Argumenten der Kommandozeile vorgenommen werden.
| |
| | |
| Eine andere Anwendung ist beispielsweise die Auswahl des letzen Parameters der Kommandozeile.
| |
| | |
| Mit \$$# erhält man die Parameterangabe (bei fünf Parametern --> $5).
| |
| | |
| Das erste Dollarzeichen wird von der Shell ignoriert (wegen des '\'), $# hingegen ausgewertet. Durch eval wird der Ausdruck nochmals ausgewertet, man erhält so den Wert des letzten Parameters:
| |
| | |
| eval \$$#
| |
| | |
| Aber Vorsicht, das klappt nur bei 1 - 9 Parametern, denn z. B. der 12. Parameter führt zu $12 --> ${1}2. Es lassen sich mit eval sogar Pointer realisieren.
| |
| | |
| Falls die Variable PTR den Namen einer anderen Variablen, z. B. XYZ, enthält, kann auf den Wert von XYZ durch eval $PTR zurückgegriffen werden, z. B. durch eval echo \$$PTR.
| |
| | |
| '''eval '''
| |
| | |
| Die Expansionen der Bash laufen nach wohldefinierten Regeln ab. Wurden sie der Reihe nach behandelt, wird die resultierende Kommandozeile ausgeführt. Manchmal enthält diese Kommandozeile wiederum Bestandteile, die man einer Expansion gern unterziehen würde. Genau hierzu verhilft eval:
| |
| | |
| '''var=foo
| |
| bla='$var'
| |
| echo $bla'''
| |
| $var
| |
| '''eval echo $bla'''
| |
| foo
| |
| | |
| = exec =
| |
| Das Kommando besitzt zwei Bedeutungen.
| |
| | |
| Wird ihm als Argument ein Kommandoname mitgegeben, so wird das aktuell ausgeführte Programm (also die Shell bzw. ein Shellskript) durch dieses neue Programm ersetzt. Das hat zur Folge, dass mit Beendigung des Kommandos auch die Shell nicht mehr existiert.
| |
| | |
| Diese Art der Anwendung von exec hat seinen Ursprung vermutlich in Zeiten begrenzter Hardwareressourcen. So "optimierte" man Shellskripte dahingehend, dass der letzte Befehl per exec gestartet wurde.
| |
| | |
| Dies ersparte eine weitere Prozesserzeugung und verlief somit etwas schneller, als es mit einem neuen Prozess der Fall gewesen wäre (und es sparte den (Speicher)Overhead für den Prozess).
| |
| | |
| Nützlich mag das Kommando in dem Sinne höchstens zum Ersetzen der aktuellen Shell durch eine andere sein:
| |
| | |
| '''echo $SHELL'''
| |
| /bin/bash
| |
| '''exec tcsh'''
| |
| /home/user>
| |
| | |
| Der zweite - und wichtigere - Anwendungsbereich für exec ist die Zuordnung eines Dateideskriptors zu einer Datei.
| |
| | |
| Angenommen, Sie möchten alle Fehlerausgaben eines Shellskripts in eine Datei umleiten.
| |
| | |
| Mit den bislang bekannten Mitteln könnten sie entweder alle kritschen Kommandos im Shellskript separat umleiten oder Sie könnten alle Kommandos gruppieren und die Fehlerausgabe gemeinsam abfangen.
| |
| | |
| Einfacher ist es, folgende Zeile an den Anfang des Skripts zu setzen:
| |
| | |
| exec 2>error.log
| |
| | |
| Erläuterung: Hiermit wird die Fehlerausgabe (Deskriptor 2) mit der Datei "error.log" verbunden.
| |
| | |
| Mit Beendigung des Shellskripts geht die Bindung wieder verloren.
| |
| | |
| Das zweite Beispiel demonstriert das Öffnen einer Datei mit exec, sodass die Eingabe aus dieser bezogen wird. Wir simulieren das Kommando nl, das die Zeilen seiner Eingabe nummeriert:
| |
| | |
| '''(typeset -i n=1; exec < testdat;'''
| |
| > while read line; do
| |
| > echo "$n $line"; n=n+1;
| |
| > done)
| |
| 1 eins
| |
| 2 zwei
| |
| 3 drei
| |
| 4 vier
| |
| | |
| Erläuterung: Die Testdatei enthält die Zeilen "eins", "zwei" usw.; die Eingabe wird aus dieser bezogen. Mittels read wird zeilenweise gelesen und jede Zeile mit vorangestellter Nummer ausgegeben.
| |
| | |
| Das Rechnen mit "n" ist möglich, da die Variable zuvor als Ganzzahl vereinbart wurde. Alles wurde in einer Subshell gestartet, damit die aktuelle Shell nicht beendet wird.
| |
| | |
| Ein letztes Beispiel soll die Thematik vorerst beenden (die Shellprogrammierung ist ein wesentlich ergiebigeres Anwendungsfeld für exec).
| |
| | |
| Es demonstriert eine effiziente Möglichkeit, eine konkrete Zeile einer Datei zu manipulieren. Unsere Testdaten seien die Folgenden:
| |
| | |
| '''cat testfile'''
| |
| Erste Zeile.
| |
| Zweite Zeile.
| |
| Zweite Zeile.
| |
| Vierte Zeile.
| |
| | |
| Aus der Datei müssen wir nicht nur lesen, sondern gleichzeitig in diese schreiben können. Wir werden nach der Zeile "Zweite Zeile." suchen und die folgende Zeile durch "Dritte Zeile." ersetzen.
| |
| | |
| Eine Kommandofolge, die dies realisiert, ist diese:
| |
| | |
| '''(exec <>testfile 1>&0'''
| |
| > while read line; do
| |
| > echo $line | grep -q "Zweite*" && echo -n "Dritte Zeile."
| |
| > done)
| |
| | |
| Erläuterung: Die Eingabedatei zum Lesen und Schreiben zu öffnen, würde allein nichts nützen, da hiermit nur der Dateideskriptor (Nummer 0) betroffen ist.
| |
| | |
| Deshalb muss die Standardausgabe ebenfalls auf diesen Deskriptor umgelenkt werden. Wird die mit "Zweite..." beginnende Zeile gefunden, zeigt der Dateizeiger bereits auf den Beginn der dritten Zeile. Deshalb landet die Ausgabe "echo..." genau dort.
| |
| | |
| Wenn Sie Zweifel an den Optionen von grep bzw. echo hegen, so testen Sie, was passiert, wenn Sie diese entfernen.
| |
| | |
| '''exec '''
| |
| | |
| Ähnlich wie beim Dot-Kommando wird keine Subshell erzeugt, sondern die Kommandozeile in der aktuellen Umgebung ausgeführt.
| |
| | |
| Eine erste Anwendung liegt darin, das aktuelle Programm durch ein anderes zu überlagern. Wenn Sie z. B. die Bourne-Shell als Login-Shell haben, aber lieber mit der C-Shell arbeiten, können sie die Bourne-Shell durch die Kommandozeile
| |
| | |
| exec /bin/csh
| |
| | |
| als letzte Zeile in der .profile-Datei durch die C-shell ersetzen (Wenn Sie die C-Shell nur Aufrufen, müssen Sie beide Shells beenden, um sich auszuloggen).
| |
| | |
| Das Kommando entspricht also dem Systemcall exec(). Wird jedoch kein Kommando angegeben, kann die E/A der aktuellen Shell dauerhaft umgeleitet werden. Beispiel:
| |
| | |
| exec 2>fehler
| |
| | |
| leitet alle folgenden Fehlerausgaben in die Datei "fehler" um, bis die Umleitung explizit durch
| |
| | |
| exec 2>-
| |
| | |
| zurückgenommen wird. Es können bei exec auch andere Dateideskriptoren verwendet werden. Ebenso kann auch die Dateiumleitung einer Eingabedatei erfolgen, z. B.:
| |
| | |
| exec 3< datei
| |
| | |
| Danach kann mit read <&3 von dieser Datei gelesen werden, bis die Umleitung mit exec 3<- wieder zurückgenommen wird.
| |
| | |
| Man kann also in Shellskripten durch das Einfügen einer exec-Anweisung die Standardausgabe/-eingabe global für das gesamte Skript umleiten, ohne weitere Änderungen vornehmen zu müssen (eine andere Möglichkeit wäre die oben beschriebene Verwendung von { }).
| |
| | |
| = exit =
| |
| Wie schon bei der interaktiven Shell kann auch eine Shell-Skript mit exit abgebrochen werden.
| |
| | |
| Vom Terminal aus kann mit der DEL-Taste abgebrochen werden, sofern das Signal nicht abgefangen wird (siehe trap). Die Syntax der exit-Anweisung lautet wie folgt:
| |
| | |
| exit [ n ]
| |
| | |
| Die exit-Anweisung wird benutzt, um ein Skript zu beenden. Wenn der Parameter n angegeben wird, wird er von dem Skript als Exit-Code zurückgegeben.
| |
| | |
| '''exit [n] '''
| |
| | |
| Beendet die Shell (das Shellskript) mit dem angegebenem Rückgabewert. Wird kein Wert angegeben, liefert exit den Status des letzten Kommandos.
| |
| | |
| = export =
| |
| Dient zum exportieren von Variablen und - mit der Option -f von Funktionen, so dass diese ab der (Shell)Prozess ihrer Definition auch in allen abgeleiteten Prozessen sichtbar sind ("globale Variablen").
| |
| | |
| Mit der Option -n kann die export-Eigenschaft entzogen werden. -p listet alle exportierten Variablen und Symbole auf:
| |
| | |
| PATH=$PATH:/usr/local/bin
| |
| export PATH
| |
| | |
| = fc =
| |
| Siehe unter Manipulation der History-Einträge
| |
| | |
| = fg [Job] =
| |
| | |
| Holt den angegebenen ("Jobnummer") bzw. den zuletzt gestarteten Hintergrundprozess in den Vordergrund.
| |
| | |
| = getopts OPTIONEN Variable =
| |
| Jeder Programmierer kennt den Aufwand beim Parsen der an ein Programm übergebenen Argumente und Optionen. Sind die Optionen erlaubt? Stimmt die Reihenfolge? Ist das Argument zulässig?...?
| |
| | |
| Die meisten Programmiersprachen bringen in ihrem Sprachschatz eine Funktion mit, die eine solche Auswertung wesentlich vereinfacht. Die Funktion der Bash ist »getopts«.
| |
| | |
| Dieses Kommando erlaubt einem Shellskript die unter Unix übliche Gruppierung von Optionen zu verwenden. Anstatt "-l -a -z" kann auch "-laz" oder "-a -lz"... geschrieben werden.
| |
| | |
| Solche Angaben über die bereits besprochenen Positionsparameter auszuwerten, ist zwar denkbar, aber mehr als verzwickt.
| |
| | |
| Im Zusammenhang mit der Bashprogrammierung werden wir »getopts« extensiv verwenden, an dieser Stelle soll ein kleines Beispiel das Gefühl für die Anwendung schulen.
| |
| | |
| Ein Skript soll die Optionen "-a", "-l", "-F" und "-f <Datei>" verstehen.
| |
| | |
| Beachten Sie, dass "-f" die Angabe eines Arguments erfordert. Die notwendige Zeichenkette der OPTIONEN ist "alf:F".
| |
| | |
| Die Reihenfolge der Optionen ist unwichtig, entscheidend ist der Doppelpunkt hinter "-f:", der »getopts« mitteilt, dass dieser Option ein Argument folgen muss:
| |
| | |
| '''cat parseline'''
| |
| #!/bin/sh
| |
|
| |
| while getopts alf:F Optionen; do
| |
| case $Optionen in
| |
| a) echo "Option a";;
| |
| l) echo "Option l";;
| |
| f) echo "Option f Argument ist $OPTARG";;
| |
| F) echo "Option F";;
| |
| esac
| |
| done
| |
|
| |
| '''parseline -aF -f'''
| |
| Option a
| |
| Option F
| |
| ./parseline: option requires an argument – f
| |
|
| |
| '''parseline -f so_gehts -l'''
| |
| Option f Argument ist so_gehts
| |
| Option l
| |
| | |
| Benötigt eine Option ein Argument, kann auf dieses über die Variable OPTARGS zugegriffen werden; OPTIND enthält zu jedem Zeitpunkt den Index auf die nächste von getopts zu betrachtende Option.
| |
| | |
| In Shellskripten wird man Fehlermeldungen von getopts abfangen. Dies geht entweder über die Umleitung der Standardfehlerausgabe oder durch Setzen der Variable OPTERR auf 0.
| |
| | |
| = hash =
| |
| Ein auf der Kommandozeile angegebenes Kommando muss von der Shell gesucht werden.
| |
| | |
| Die Suche, vor allem wenn sie die Angaben aus PATH einschließt, kostet Zeit. Deswegen merkt sich die Bash die Zugriffspfade zu allen externen Kommandos in einer Hashtabelle.
| |
| | |
| Diese Hashtabelle wird zuerst konsultiert (es sei denn hashall ist nicht gesetzt; vergleiche set) und nur wenn der Pfad zu einem Kommando dort nicht erfasst wird, werden die Verzeichnispfade betrachtet.
| |
| | |
| Beim nächsten Zugriff auf dasselbe Kommando wird man den Geschwindigkeitszuwachs deutlich spüren.
| |
| | |
| Zur Anzeige der Hashtabelle ist »hash« ohne Angabe von Argumenten aufzurufen:
| |
| | |
| hash
| |
| hits command
| |
| 2 /bin/ls
| |
| 1 /bin/mv
| |
| 6 /bin/sh
| |
| 8 /usr/bin/vi
| |
| 1 /bin/chmod
| |
| 3 /bin/date
| |
| 1 /usr/bin/id
| |
| 1 /usr/bin/man
| |
| | |
| Ein Problem besteht nun mit gleichnamigen Kommandos. Liegt eines in der Hashtabelle vor, so kann auf das andere nur über die vollständige Pfadangabe zugegriffen werden.
| |
| | |
| Soll dieses "benachteiligte" Kommando nun vermehrt eingesetzt werden, ist ein Löschen der Hashtabelle mittels »-r« sinnvoll:
| |
| | |
| hash -r
| |
| hash
| |
| hash: hash table empty
| |
| | |
| Indem »hash« mit einem oder mehreren Kommandonamen aufgerufen wird, werden diese Kommandos gesucht und in die Hashtabelle aufgenommen; sie werden jedoch nicht gestartet (sinnvoll ist dies eventuell in Startskripten).
| |
| | |
| Des Weiteren kann mit »-p <Pfad_zum_Kommando>« ein solches mit vorgegebenem Pfad der Tabelle hinzufügen.
| |
| | |
| = help =
| |
| Schreibt einen kurzen Hilfetext zu einem eingebauten Kommando aus.
| |
| | |
| = history =
| |
| Das Kommando dient zur Anzeige oder Manipulation des Kommandozeilenspeichers.
| |
| | |
| Ohne Optionen gerufen, werden alle Einträge der Liste inklusive einer Zeilennummerierung aufgeführt; mit einer vorangestellten Zahl kann die Darstellung auf die letzten Einträge eingeschränkt werden:
| |
| | |
| '''history 5'''
| |
| 555 parseline -aF -f
| |
| 556 parseline -f bla -l huch
| |
| 557 mv parseline Scripts\&Programs/
| |
| 558 ll Linuxfibel/bash.htm
| |
| 559 history 5
| |
| | |
| Anhand der Nummerierung kann nun gezielt ein Eintrag entfernt werden (»-d <Nummer>«). »-c« löscht den gesamten Inhalt.
| |
| | |
| Der Kommandozeilenspeicher wird bei Beendigung der Shell in einer Datei gesichert, um diese explizit zu aktualisieren, kann »-a« bzw. »-w« genutzt werden, womit die neuen Einträge angehangen werden bzw. der alte Inhalt ersetzt wird.
| |
| | |
| = jobs =
| |
| Das Kommando zeigt die in der Jobtabelle erfassten Jobs (Hintergrundprozesse) an.
| |
| | |
| Das Format der Ausgabe kann über Optionen gesteuert werden; im Zusammenhang mit Prozessen gehen wir weiter unten auf dieses Thema ein.
| |
| | |
| = kill =
| |
| Das Kommando dient der Steuerung bereits laufender Prozesse, indem es an diese Signale versendet.
| |
| | |
| Während einige Signale vordefinierte Bedeutungen besitzen, können andere von den Prozessen nach eigenen Vorstellungen behandelt werden.
| |
| | |
| Das Versenden von Signalen soll auch im Zusammenhang mit Prozessen diskutiert werden.
| |
| | |
| = let =
| |
| Für jedes Argument wird eine arithmetische Substitution versucht.
| |
| | |
| Expandiert das letzte Argument zu 0, ist der Rückgabewert 1; sonst immer 0. »let« bietet somit eine Möglichkeit der Überprüfung, ob eine Variable eine Zahl >0 enthält:
| |
| | |
| '''failure=1234x
| |
| let $failure 2>/dev/null || echo "keine Zahl"'''
| |
| keine Zahl
| |
| '''let answer=6*7'''
| |
| 42
| |
| | |
| = local =
| |
| Das Kommando kann nur innerhalb von Funktionen verwendet werden und dient der Definition lokaler Variablen. Somit ist sichergestellt, dass existierende Variablen gleichen Namens nichtversehentlich überschrieben werden:
| |
| | |
| '''var=foo
| |
| func() { var=bla; echo $var; }
| |
| func'''
| |
| bla
| |
| '''echo $var'''
| |
| bla
| |
| '''var=foo
| |
| func() { local var=bla; echo $var; }
| |
| func'''
| |
| bla
| |
| '''echo $var'''
| |
| foo
| |
| | |
| = logout =
| |
| Beendet eine Login-Bash und meldet den Benutzer ab. | |
| | |
| In einer Nicht-Login-Bash hagelt es eine Fehlermeldung. | |
| | |
| = popd =
| |
| Entfernt den obersten Eintrag vom Verzeichnisstack und wechselt zum neuen obersten Verzeichniseintrag. Dieser Wechsel kann mit der Option »-n« unterdrückt werden.
| |
| | |
| Um einen anderen Eintrag als den obersten zu entfernen, kann dieser mit »+Anzahl« angegeben werden. Der oberste Verzeichniseintrag selbst ist »+0«, der zweite »+1« usw.
| |
| | |
| Mit »-Anzahl« beginnt die Zählung am unteren Ende des Stacks. Ein Beispiel zur Anwendung folgt beim korrespondierenden »pushd«.
| |
| | |
| = printf "FORMAT" Argument[e] =
| |
| Das Kommando verhilft zu einer formatierten Ausgabe analog zum printf der Programmiersprache C.
| |
| | |
| Die FORMAT-Zeichenkette enthält hierfür Platzhalter mit optionalen Ausrichtungsparametern; die nachfolgenden Argumente müssen vom Typ her genau dem Typ des Platzhalters entsprechen.
| |
| | |
| Innerhalb der FORMAT-Zeichenkette können Escape-Sequenzen verwendet werden. Die wichtigsten sind »\n« (Zeilenumbruch), »\t« (Tabulator) und »\a« (akustisches Zeichen).
| |
| | |
| Ein Platzhalter besitzt die Form »%[Ausrichtung]Symbol«, wobei die Ausrichtung eine Zahl ist, die die Anzahl darzustellender Zeichen des Arguments betrifft.
| |
| | |
| Ist das Argument länger, werden die überschüssigen Zeichen abgeschnitten, ist es kürzer, werden Leerzeichen aufgefüllt. Mit einem optionalen Minus »-« vor der Zahl wird das Argument linksbündig angeordnet.
| |
| | |
| Wichtige Symbole sind:
| |
| {|
| |
| |- | | |- |
| | | d | | | [[popd]] || Entfernt den obersten Eintrag vom Verzeichnisstack und wechselt zum neuen obersten Verzeichniseintrag. |
| | | Eine ganze Zahl | |
| |- | | |- |
| | | s | | | [[printf]] || |
| | | Eine Zeichenkette | |
| |- | | |- |
| | | f | | | [[pushd]] || Mit dem Kommando kann in ein angegebenes Verzeichnis gewechselt werden, wobei das Verzeichnis auf einem Stack abgelegt wird |
| | | Rationale Zahl; hierbei kann die Anzahl darzustellender Vor- und Nachkommastellen angegeben werden: "%8.3f" | |
| |- | | |- |
| | | E | | | [[pwd]] || Gibt das aktuelle Arbeitsverzeichnis aus |
| | | Darstellung rationaler Zahlen in Exponentenform. | |
| |- | | |- |
| |} | | | [[read]] || |
| '''Beispiele'''
| |
| | |
| '''printf "Zeichenkette: %8s Zahl %d\n" test 42'''
| |
| Zeichenkette: test Zahl 42
| |
| '''printf "Zeichenkette:\t%8s\tZahl %d\n" test 42'''
| |
| Zeichenkette: test Zahl 42
| |
| '''printf "Zeichenkette:\t%-8s\tZahl %3.1E\n" test 42'''
| |
| Zeichenkette: test Zahl 4,2E+01
| |
| | |
| = pushd =
| |
| Mit dem Kommando kann in ein angegebenes Verzeichnis gewechselt werden, wobei das Verzeichnis auf einem Stack abgelegt wird.
| |
| | |
| Mit »-n« wird der Verzeichniswechsel verhindert, der Name des Verzeichnisses aber dennoch gespeichert. Dieser Stack kann rotiert werden, mit »-Anzahl« wird vom Ende des Stacks aus rotiert; mit »+Anzahl« vom Anfang.
| |
| | |
| Das nachfolgende Beispiel zählt alle Unterverzeichnisse ausgehend vom Startverzeichnis, wobei popd und pushd Verwendung finden:
| |
| '''cat countdir'''
| |
| #!/bin/sh
| |
|
| |
| while :; do
| |
| for i in $(ls); do
| |
| test -d $i || continue
| |
| pushd -n $(pwd)/$i &>/dev/null
| |
| number=$(($number+1))
| |
| done
| |
| popd &>/dev/null && continue
| |
| break
| |
| done
| |
| echo Anzahl: $number
| |
| | |
| = pwd =
| |
| Gibt das aktuelle Arbeitsverzeichnis aus. Mit der der Option »-P« wird der Pfad ohne enthaltene symbolische Links angegeben; mit »-L« werden Links berücksichtigt.
| |
| | |
| Beide Optionen sind sinnvoll, um die Einstellung der Variablen »physical« zu überschreiben:
| |
| | |
| '''pwd'''
| |
| /usr/X11
| |
| '''pwd -P'''
| |
| /usr/X11R6
| |
| '''set -o physical
| |
| pwd'''
| |
| /usr/X11R6
| |
| | |
| = read Variable [Variable] =
| |
| Mit »read« wird eine Eingabezeile eingelesen und deren Inhalt Variablen zugewiesen.
| |
| | |
| Die Eingabe wird anhand der in IFS vorgegebenen Trennzeichen in einzelne Token zerlegt und der Reihe nach den Variablen zugewiesen.
| |
| | |
| Stehen mehr Token zur Verfügung als Variablen, so wird die letzte Variable mit allen noch nicht zugewiesenen Token belegt; stehen weniger Token bereit, bleibt der Inhalt der überschüssigen Variablen leer:
| |
| | |
| '''read a b c'''
| |
| 1 2 3 4 5
| |
| '''echo "a=$a"; echo "b=$b"; echo "c=$c"'''
| |
| a=1
| |
| b=2
| |
| c=3 4 5
| |
| | |
| Ist die Anzahl erwarteter Token nicht vorhersehbar, bietet sich die Verwendung einer Feldvariablen an. Hierzu ist dem Variablennamen einzig die Option »-a« voranzustellen:
| |
| | |
| '''read -a feld'''
| |
| Jedes Wort gelangt in ein eigenes Feld.
| |
| '''echo "3.Element: ${feld[2]}"'''
| |
| 3.Element: gelangt
| |
| | |
| Für die Shellprogrammierung sind zwei weitere Optionen nützlich. Zum einen »-p Prompt«, womit die erwartete Eingabe durch ein Prompt signalisiert wird und »-t Timeout«, wodurch das Kommando nach Ablauf der angegebenen Zeitspanne (Sekunden) mit einem Fehlerwert zurück kehrt:
| |
| | |
| '''read -p "Eingabe: " -t 5 || echo "nichts gedrückt"'''
| |
| # Finger weg von der Tastatur!
| |
| Eingabe: nichts gedrückt
| |
| | |
| = readonly =
| |
| Variablen und Funktionen lassen sich nachträglich als »nicht änderbar« deklarieren.
| |
| | |
| Um eine einfache Variable nur-lesend zu vereinbaren, genügt die Angabe ihres Namens; bezieht man sich auf eine Funktion, so ist »-f Funktionsname« anzugeben.
| |
| | |
| Eine Feldvariable bewahrt die Option »-a Feldvariable« vor versehentlichem Überschreiben. Wird »readonly« ohne Angabe von Optionen oder Variablennamen aufgerufen, erhält man eine Auflistung aller »read-only«-Variablen und -Funktionen.
| |
| | |
| = return [n] =
| |
| Dient zum Rücksprung aus einer Funktion. Mit [n] kann ein Rückgabewert vereinbart werden, ansonsten wird der Status des zuletzt innerhalb der Funktion ausgeführten Kommandos geliefert.
| |
| | |
| = set =
| |
| [[Linux:Shell:Bash:Builtin:set | set dient zum Setzen bash-interner Variablen]]
| |
| | |
| = shift [n] =
| |
| Dient zum Verschieben der Positionsparameter ; ohne weitere Angaben wird die Liste der Positionsparameter um eine Stelle nach links verschoben; mit Angabe eine Ziffer wird um die spezifizierte Anzahl Stellen rotiert.
| |
| | |
| = shopt =
| |
| Dient zum Setzen bash-interner Variablen, die das Verhalten der Shell maßgeblich beeinflussen. Nähere Informationen wurden bereits weiter oben gegeben.
| |
| | |
| = suspend =
| |
| Suspendiert die Shell. Sie kann nur durch ein Signal SIGCONT reaktiviert werden.
| |
| | |
| = test Ausdruck =
| |
| test liefert in Abhängigkeit vom Wahrheitswert des Ausdrucks 0 (wahr) oder 1 (falsch) zurück und ist damit ein wichtiger Bestandteil vieler Shellskripten.
| |
| | |
| Es existieren mannigfaltige Klassen von Tests. Doch bevor wir Ihnen eine Auswahl verfügbarer Tests vorstellen, möchten wir auf eine alternative Schreibweise hinweisen, die gern bei bedingter Ausführung eingesetzt wird.
| |
| | |
| Im nachfolgenden Beispiel sind die beiden Zeilen semantisch äquivalent:
| |
| | |
| '''test -z $DISPLAY
| |
| [ -z $DISPLAY ]'''
| |
| | |
| Beachten Sie, dass nach der öffnenden eckigen Klammer und vor der schließenden zwingend ein Whitespace stehen muss!
| |
| | |
| Die wohl wichtigsten Tests befassen sich mit Dateien(alle Tests schließen einen Existenztest der Datei mit ein):
| |
| | |
| {| class="wikitable sortable"
| |
| |- | | |- |
| | | '''-b/-c ''' | | | [[readonly]] || Variablen und Funktionen lassen sich nachträglich als »nicht änderbar« deklarieren. |
| | | Test auf Gerätedatei (Block/Character): | |
| | | '''test -b - /dev/hda; echo $?'''
| |
| 0
| |
| '''test -b /dev/console; echo $?'''
| |
| 1
| |
| |- | | |- |
| | | '''-d ''' | | | [[return]] || Rücksprung aus einer Funktion |
| | | Test auf Verzeichnis: | |
| | | '''for i in $(ls|head -5); do'''
| |
| >(test -d $i && echo "$i ist ein Verzeichnis")
| |
| >|| echo "$i ist kein Verzeichnis"
| |
| > done
| |
| Desktop ist ein Verzeichnis
| |
| Linuxfibel ist ein Verzeichnis
| |
| Systemprogrammierung ist ein Verzeichnis
| |
| allekapitel.htm ist kein Verzeichnis
| |
| amanda.rpm ist kein Verzeichnis
| |
| |- | | |- |
| | | '''-e ''' | | | [[set]] || Setzen bash-interner Variablen |
| | | Existenz der Datei
| |
| | |
| |
| |- | | |- |
| | | '''-f ''' | | | [[shift]] || Verschieben der Positionsparameter |
| | | Test auf normale Datei: | |
| | | '''test -f /dev/hda; echo $?'''
| |
| 1
| |
| |- | | |- |
| | | '''-k ''' | | | [[shopt]] || Dient zum Setzen bash-interner Variablen, die das Verhalten der Shell maßgeblich beeinflussen |
| | | Test, ob das »sticky«-Flag auf ein Verzeichnis gesetzt ist:
| |
| | | '''test -k /tmp; echo $?'''
| |
| 0
| |
| |- | | |- |
| | | '''-p ''' | | | [[suspend]] || Suspendiert die Shell. Sie kann nur durch ein Signal SIGCONT reaktiviert werden. |
| | | Test auf Pipe: | |
| | | '''test -p /dev/xconsole; echo $?'''
| |
| 0
| |
| |- | | |- |
| | | '''-r/-w/-x ''' | | | [[test]] || Bedingungen prüfen |
| | | Test auf Lese-/Schreib-/Ausführungsrecht
| |
| | |
| |
| |- | | |- |
| | | '''-s ''' | | | [[time]] || Report time consumed by pipeline's execution |
| | | Test, ob eine Datei nicht leer ist
| |
| | |
| |
| |- | | |- |
| | | '''-u ''' | | | [[times]] || Zeit der Shell und von ihr gestarteter Kommandos messen |
| | | Test, ob das »suid«-Flag auf einer Datei gesetzt ist: | |
| | | '''test -u /usr/bin/passwd; echo $?'''
| |
| 0
| |
| |- | | |- |
| |} | | | [[trap]] || |
| | |
| '''Datei_1 -nt Datei_2 bzw. Datei_1 -ot Datei_2 '''
| |
| | |
| Test, ob Datei_1 »neuer« bzw. »älter« ist als die Datei_2
| |
| '''Datei_1 -ef Datei_2 '''
| |
| | |
| Test, ob Datei_1 und Datei_2 den selben Inode auf demselben Device besitzen (die eine Datei ist ein harter Link auf die andere):
| |
| '''ln bla foo
| |
| test bla -ef foo; echo $?'''
| |
| 0
| |
| | |
| Des Weiteren existieren eine Reihe von Operatoren zum Vergleich von Zeichenketten:
| |
| '''-z Zeichenkette '''
| |
| Der Test ist wahr, wenn die Zeichenkette die Länge 0 hat
| |
| | |
| '''-n string '''
| |
| Der Test ist wahr, wenn die Länge der Zeichenkette >0 ist
| |
| | |
| '''Zeichenkette_1 == Zeichenkette_2 '''
| |
| Wahr, wenn die Zeichenketten gleich sind
| |
| | |
| '''Zeichenkette_1 != Zeichenkette_2 '''
| |
| Wahr, wenn die Zeichenketten ungleich sind
| |
| | |
| '''Zeichenkette_1 < Zeichenkette_2 '''
| |
| Wahr, wenn die Zeichenkette_1 lexikalisch kleiner ist als Zeichenkette_2
| |
| | |
| '''Zeichenkette_1 > Zeichenkette_2 '''
| |
| Wahr, wenn die Zeichenkette_1 lexikalisch größer ist als Zeichenkette_2
| |
| | |
| Eine vielseitige Anwendung ist der Vergleich von Argumenten mit den Operatoren -eq (gleich), -ne (ungleich), -gt (größer als), -lt (kleiner als), -ge (größer als oder gleich) und -le (kleiner als oder gleich):
| |
| | |
| # Überprüfung der Anzahl Parameter in einem Shellskript...
| |
| '''if [ "$#" -lt "3" ]; then echo "Zu wenige Parameter"; exit 1; fi'''
| |
| | |
| '''Anmerkung '''
| |
| Die Prüfung und Beendigung eines Skripts im Fehlerfall lässt sich eleganter über die Parametersubstitution realisieren:
| |
| | |
| # Elegante Überprüfung der Anzahl Parameter in einem Shellskript...
| |
| '''var_3 = ${3:?Zu wenige Parameter}'''
| |
| | |
| Mehrere Tests können kombiniert werden:
| |
| '''! '''Negation
| |
| '''-a '''Logisches UND zweier Tests
| |
| '''-o '''Logisches ODER zweier Tests
| |
| '''test -b /dev/null -o -c /dev/null
| |
| test $? -eq 0 && echo "Gerätedatei"'''
| |
| Gerätedatei
| |
| | |
| = times =
| |
| * Misst die Zeit für die Shell und der von dieser gestarteten Kommandos.
| |
| | |
| Ausgegeben wird die User- und die Systemzeit (nicht jedoch die Realzeit, dies vermag das Kommando time):
| |
| times ls 0m0.090s 0m0.030s 0m0.160s 0m0.160s
| |
| | |
| = trap =
| |
| trap 'Kommandoliste' Signale
| |
| | |
| * Ausführen der Kommandoliste, wenn eins der angegebenen Signale an den Prozeß (= Shell) gesendet wird.
| |
| * Die Signale werden in Form der Signalnummern oder über ihre Namen (SIGKILL, SIGHUP, ...), getrennt durch Leerzeichen aufgeführt.
| |
| * Ist die Kommandoliste leer, werden die entsprechenden Signale abgeschaltet. Bei einfachen Kommandos reichen oft auch die Anführungszeichen, um die Shell-Ersetzung zu verhindern.
| |
| * Signale sind eine Möglichkeit, wie verschiedenen Prozesse, also gerade laufende Programme, miteinander kommunizieren können.
| |
| * Ein Prozeß kann einem anderen Prozeß ein Signal senden (der Betriebssystemkern spielt dabei den Postboten).
| |
| * Der Empfängerprozeß reagiert auf das Signal, z. B. dadurch, dass er sich beendet. Der Prozeß kann das Signal auch ignorieren.
| |
| * Das ist beispielsweise nützlich, wenn ein Shellskript nicht durch den Benutzer von der Tastatur aus abgebrochen werden soll.
| |
| * Mit dem trap-Kommando kann man festlegen, mit welchen Kommandos auf ein Signal reagiert werden soll bzw. ob überhaupt reagiert werden soll.
| |
| | |
| Neben anderen können folgende Signalnummern verwendet werden:
| |
| | |
| {| class="wikitable sortable"
| |
| |- | | |- |
| | | '''0''' | | | [[type]] || |
| | | '''SIGKILL''' | |
| | | Terminate (beim Beenden der shell)
| |
| |- | | |- |
| | | '''1''' | | | [[typeset]] || declare |
| | | '''SIGHUP''' | |
| | | Hangup (beim Beenden der Verbindung zum Terminal oder Modem)
| |
| |- | | |- |
| | | '''2''' | | | [[ulimit]] || |
| | | '''SIGINT''' | |
| | | Interrupt (wie Strg-C-Taste am Terminal)
| |
| |- | | |- |
| | | '''3''' | | | [[umask]] || Zugriffsrechte für neue Dateien steuern |
| | | '''SIGQUIT''' | |
| | | Abbrechen (Beenden von der Tastatur aus)
| |
| |- | | |- |
| | | '''9''' | | | [[unalias]] || Löschen von Aliasen |
| | | '''SIGKILL''' | |
| | | Kann nicht abgefangen werden - Beendet immer den empfangenden Prozeß
| |
| |- | | |- |
| | | '''15''' | | | [[unset]] || Löschen einer Variable oder Funktion |
| | | '''SIGTERM''' | |
| | | Terminate (Software-Terminate, Voreinstellung)
| |
| |- | | |- |
| | | [[wait]] || Warten auf einen oder alle Hintergrundprozesse |
| |} | | |} |
|
| |
|
| Eine Liste aller Signale gibt folgendes Kommando aus:
| | == Aufruf == |
| kill -l
| | <syntaxhighlight lang="bash" highlight="1" line> |
| | |
| === Beispiele === | |
| # Skript sperren gegen Benutzerunterbrechung:
| |
| trap "" 2 3
| |
| | |
| oder auch
| |
| | |
| # Skript sauber beenden
| |
| trap 'rm tmpfile; cp foo fileb; exit' 0 2 3 15
| |
| | |
| Bitte nicht das exit-Kommando am Schluss vergessen, sonst wird das Skript nicht beendet.
| |
| | |
| Wiedereinschalten der Signale erfolgt durch trap [Signale]. Ein letztes Beispiel zu trap:
| |
| # Automatisches Ausführen des Shellskripts .logoff beim
| |
| # Ausloggen durch den folgenden Eintrag in .profile:
| |
| trap .logoff 0
| |
| | |
| '''trap '''
| |
| * Viele Programme lassen sich während der Laufzeit über bestimmte Signale beenden oder unterbrechen (bspw. schießt [Strg]+[C] fast jedes Programm ab).
| |
| * »trap« kann nun auf zwei Arten verwendet werden.
| |
| * Zum einen kann ein Signal (außer SIGKILL, Nr. 9) von der Behandlung durch die Bash ausgeschlossen werden.
| |
| | |
| Dazu lässt man trap ein paar leerer Anführungsstriche und die Liste der zu ignorierenden Signalnummern (die Nummern erhält man mit "kill -l") folgen:
| |
| '''sleep 100
| |
| [Strg]+[C]''' # Sofortiger Abbruch durch Signal SIGINT (Nr.2)
| |
|
| |
| '''trap "" 2
| |
| ''''# Die Bash interessiert sich nun nicht mehr für SIGINT: sleep 100
| |
| '''[Strg]+[C]''' # Kein Abbruch
| |
| | |
| Die ursprüngliche Bedeutung eines Signals kann durch die Angabe von »trap Signalnummer« wieder hergestellt werden.
| |
| | |
| Die zweite Verwendung von »trap« erlaubt die Verbindung von Kommandos mit bestimmten Signalen. Trifft ein solches ein, wird das vereinbarte Kommando aufgerufen:
| |
| | |
| '''trap 'echo "SIGINT empfangen"' 2
| |
| [Strg]+[C]'''SIGINT empfangen
| |
| | |
| | |
| trap ist somit für Shellskripte interessant, die mit temporären Dateien arbeiten, um diese bei Abbruch durch ein Signal ordnungsgemäß aufräumen zu können.
| |
| | |
| Die Option -p bringt alle von trap veränderten Signale mit ihrer Belegung zum Vorschein.
| |
| | |
| = type =
| |
| Das Kommando verrät »etwas mehr« über ein als Argument angegebenes Kommando. Ohne Option verrät es, ob das Argument ein builtin-Kommando, eine Funktion,... oder ein auf der Platte liegendes Programm ist:
| |
| '''type test'''
| |
| test is a shell builtin
| |
|
| |
| '''type passwd'''
| |
| passwd is /usr/bin/passwd
| |
| | |
| Etwas bedeckt hält sich type -t, was die Art des Arguments mit einem knappen Wort erklärt:
| |
| | |
| '''type -t test'''
| |
| builtin
| |
|
| |
| '''type -t passwd'''
| |
| file
| |
| | |
| -a lässt das Kommando alle Interpretationen ausgeben und ist bei der Suche nach einem Kommando sicher eine nette Hilfe:
| |
| | |
| '''type -a test'''
| |
| test is a shell builtin
| |
| test is /usr/bin/test
| |
| | |
| Schließlich beschränkt die Option -p die Suche auf die auf der Platte gespeicherten Programme, in vielen Distributionen hat sich dafür which eingebürgert:
| |
| | |
| '''type which'''
| |
| which is aliased to `type -p'
| |
| | |
| = typeset =
| |
| Siehe '''declare'''
| |
| | |
| = ulimit =
| |
| Mit diesem Befehl können die von der Shell und aus dieser gestarteten Prozesse verfügbaren Ressourcen beschränkt werden.
| |
| | |
| Der Administrator kann durch Verwendung des Kommandos in der /etc/profile einem jeden Benutzer, dessen Login-Shell die Bash ist, unwiderrufliche Schranken auferlegen.
| |
| | |
| Der Benutzer kann diese Werte dann nur verringern; aber niemals erhöhen (dies darf einzig Root).
| |
| | |
| Jede Ressource kann durch zwei Werte beschränkt werden. Das Softlimit kann überschritten werden, während die Anforderung von Ressourcen, die das Hardlimit überschreiten mit einer Fehlermeldung abgewiesen werden. Softlimit setzt man mit der Option -L, das Hardlimit mit -H; ohne Option werden beide Limits mit ein und denselben Wert belegt.
| |
| | |
| Die Option -a bringt alle Ressourcen und die Softlimits zum Vorschein:
| |
| | |
| '''ulimit -a'''
| |
| core file size (blocks) 0 # -c
| |
| data seg size (kbytes) unlimited # -d
| |
| file size (blocks) unlimited # -f
| |
| max locked memory (kbytes) unlimited # -l
| |
| max memory size (kbytes) unlimited # -m
| |
| open files 1024 # -n
| |
| pipe size (512 bytes) 8 # -p
| |
| stack size (kbytes) unlimited # -s
| |
| cpu time (seconds) unlimited # -t
| |
| max user processes 1024 # -u
| |
| virtual memory (kbytes) unlimited # -v
| |
| | |
| Hinter den einzelnen Ausgabezeilen haben wir die Optionen eingefügt, die Sie zur Manipulation eines konkreten Limits angeben müssen.
| |
| | |
| Vielleicht ist zu dem einen oder anderen Limit noch eine Anmerkung notwendig, da vermutlich nicht jeder Leser ein Programmierer ist.
| |
| | |
| Eine core-Datei ist ein Speicherauszug, also ein Abbild des RAM. Linux schreibt den Speicherbereich eines Prozesses, falls jener mit einem schwerwiegenden Fehler abbricht (z.B. Speicherschutzverletzung) in eine Datei, die anschließend mittels eines Debuggers nach der Fehlerursache hin untersucht werden kann.
| |
| | |
| Dazu bedarf es allerdings weit reichender Programmiererfahrungen. Da diese Cores durchaus mehrere MByte groß werden können, empfiehlt sich deren Anlegen zu unterbinden (Wert 0).
| |
| | |
| Zu jedem Prozess gehören neben dem im RAM liegen0,10cmden Programm noch ein Datensegment für (der Name sagt's schon) die Daten und ein Stack, der u.a zur Wertübergabe zwischen Funktionen verwendet wird. Wer nicht genau weiß, was er tut, tut gut daran, mit diesen Limits nichts zu tun.
| |
| | |
| Die weiteren Werte sollten selbsterklärend sein. Der Systemadministrator ist berechtigt, ein Limit aufzuheben, indem er an Stelle des Wertes das Schlüsselwort unlimited angibt.
| |
| | |
| Abschließend sei noch erwähnt, dass die vom System vorgegebenen Grenzen mit den hiesigen Werten nicht manipuliert werden können; dies geht nur durch Erzeugung eines neuen Kernels oder durch Änderungen einiger Parameter zur Laufzeit (siehe Prozessdateisystem).
| |
| | |
| = umask =
| |
| Setzt die Rechtemaske für neu erzeugte Dateien oder Verzeichnisse bzw. zeigt die Rechte an.
| |
| | |
| Die Option -S veranlasst die Verwendung einer symbolischen anstatt der voreingestellten nummerischen Angabe:
| |
| | |
| '''umask -S'''
| |
| u=rwx,g=rx,o=rx
| |
| | |
| Weitere Beispiele finden Sie im Abschnitt Zugriffsrechte.
| |
| | |
| = unalias =
| |
| Löscht den angegebenen Alias bzw. mit der Option -a alle Aliasse.
| |
| | |
| = unset =
| |
| Dient zum Löschen einer Variable oder Funktion.
| |
| | |
| = wait =
| |
| Dient zum Warten auf einen oder alle Hintergrundprozesse. Wird keine Prozess- oder Jobnummer angegeben, so wird auf die Terminierung aller Hintergrundprozesse gewartet und der Rückgabewert ist 0. Mit Spezifizierung einer Nummer wird genau auf den betreffenden Prozess gewartet und dessen Rückgabestatus ist der Rückgabewert von »wait«.
| |
| | |
| = Links =
| |
| == Dateien ==
| |
| | |
| == Man-Pages ==
| |
| | |
| == Intern ==
| |
| | |
| == Weblinks ==
| |
|
| |
|
| | </syntaxhighlight> |
| | === Optionen === |
| | === Parameter === |
| | === Umgebungsvariablen === |
| | === Exit-Status === |
| | == Anwendung == |
| | === Problembehebung === |
| | == Konfiguration == |
| | === Dateien === |
| | <noinclude> |
| | == Anhang == |
| | === Siehe auch === |
| | {{Special:PrefixIndex/{{BASEPAGENAME}}}} |
|
| |
|
| [[Kategorie:Linux:Shell:Bash:Builtin]]
| | ==== Dokumentation ==== |
| | ===== Man-Page ===== |
| | ===== Info-Pages ===== |
| | ==== Links ==== |
| | ===== Weblinks ===== |
|
| |
|
| [[Kategorie:Linux:Shell:Bash]] | | [[Kategorie:Bash/Builtin]] |
| | </noinclude> |