Arbeitsweise der Shell
Die Shell ist ein Programm
Abschnitt betitelt „Die Shell ist ein Programm“Die Shell ist kein Teil des Kernels und auch nicht «das Terminal». Sie ist ein ganz normales Programm, das eine Zeile liest, sie interpretiert und dann andere Programme startet. Das Terminal ist nur das Fenster, in dem die Shell läuft. Wenn du verstehst, was die Shell mit deiner Eingabe macht, bevor überhaupt ein Programm startet, werden viele scheinbar seltsame Verhaltensweisen logisch.
Die sechs Schritte
Abschnitt betitelt „Die sechs Schritte“Für jede Zeile, ob interaktiv eingetippt oder aus einem Skript gelesen, arbeitet die Bash dieselbe Folge ab:
flowchart TD
A["1 · Zeile analysieren<br/>Befehl, Optionen, Argumente trennen"] --> B["2 · Befehl suchen<br/>Alias → Funktion → Builtin → PATH"]
B --> C["3 · Umleitungen und Pipes einrichten<br/>> >> < 2> |"]
C --> D["4 · Sonderzeichen ersetzen<br/>* ? {a,b} ~ $VAR $(...)"]
D --> E["5 · Ablauf steuern<br/>&& || ; if"]
E --> F["6 · Programm ausführen<br/>warten, Exit-Status merken"]
F -->|nächste Zeile| A
Streng genommen passieren Schritt 3 und 4 in der Bash in einer etwas anderen Reihenfolge, aber als Denkmodell reicht diese Liste völlig. Die Schritte 3 und 4 bekommen auf den nächsten zwei Seiten je eine eigene Seite. Hier geht es um die Schritte 1, 2, 5 und 6.
Schritt 1: Zeile analysieren
Abschnitt betitelt „Schritt 1: Zeile analysieren“Die Shell zerlegt die Zeile an Leerzeichen in Wörter. Das erste Wort ist der Befehl, der Rest sind Optionen und Argumente:
ls -lt /etcls ist der Befehl, -lt sind zwei Optionen, /etc ist das Argument. Für die Shell sind das drei Wörter, die sie dem Programm ls weiterreicht. Was eine Option bedeutet, weiss nur ls selbst. Merke dir: Leerzeichen trennen Wörter. Genau deshalb sind Dateinamen mit Leerzeichen heikel, dazu mehr bei Metazeichen und Quoting.
Schritt 2: Befehl suchen
Abschnitt betitelt „Schritt 2: Befehl suchen“Die Bash sucht den Befehl in dieser Reihenfolge und nimmt den ersten Treffer:
- Alias: eine Abkürzung, die du selbst definiert hast (
alias ll='ls -alF'). - Funktion: eine Shell-Funktion, zum Beispiel aus
~/.bashrc. - Builtin: ein Befehl, der in die Shell eingebaut ist, etwa
cd,echo,pwd,type,export. - Programm im PATH: ein ausführbares File in einem der Verzeichnisse, die in der Variable
PATHstehen, von links nach rechts durchsucht.
Findet sie nichts, kommt die bekannte Meldung bash: xyz: command not found.
Hands-on: Der Befehl type sagt dir, was die Shell gefunden hat.
type cdtype lstype lltype -a echoWas erwartest du? cd ist ein Builtin, ls wird auf Ubuntu als Alias für ls --color=auto gemeldet, ll ist ebenfalls ein Alias. type -a zeigt alle Treffer: echo gibt es als Builtin und als Programm /usr/bin/echo. Das Builtin gewinnt.
Warum muss cd ein Builtin sein? Ein externes Programm läuft als eigener Prozess und kann das Arbeitsverzeichnis seines Elternprozesses (der Shell) nicht ändern. Das Verzeichnis zu wechseln geht nur, wenn die Shell es selbst tut.
Der Suchpfad PATH
Abschnitt betitelt „Der Suchpfad PATH“echo "$PATH"Du siehst eine Liste von Verzeichnissen, getrennt durch Doppelpunkte, auf Ubuntu etwa:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binDer Reihe nach wird in jedem dieser Verzeichnisse nach einer Datei mit dem Befehlsnamen gesucht. Darum liegt /usr/local/bin vor /usr/bin: Selbst installierte Programme sollen die Systemversion überstimmen können.
Eigene Skripte gehören nach ~/bin. Ubuntu fügt dieses Verzeichnis beim Login automatisch zum PATH hinzu, sofern es existiert:
mkdir -p ~/bincat > ~/bin/hallo <<'EOT'#!/bin/bashecho "Hallo von $(whoami)"EOTchmod +x ~/bin/hallohalloFalls die Shell hallo nicht findet, war ~/bin beim Login noch nicht da. Melde dich einmal ab und wieder an oder lade ~/.profile neu mit source ~/.profile. Mehr dazu auf der Seite Variablen und Umgebung.
Schritt 6: Ausführen und Exit-Status
Abschnitt betitelt „Schritt 6: Ausführen und Exit-Status“Die Shell startet das Programm, wartet, bis es fertig ist, und merkt sich dessen Exit-Status: eine Zahl zwischen 0 und 255. Die Konvention ist einfach: 0 heisst Erfolg, alles andere heisst Fehler. Den Status des letzten Befehls findest du in der Variable $?.
Hands-on:
ls /etc/passwdecho $?ls /gibtsnichtecho $?trueecho $?falseecho $?true und false sind winzige Programme, die nichts anderes tun, als 0 beziehungsweise 1 zurückzugeben. Sie sind praktisch zum Testen.
Schritt 5: Ablauf steuern
Abschnitt betitelt „Schritt 5: Ablauf steuern“Mit dem Exit-Status kannst du direkt auf der Befehlszeile Entscheidungen treffen:
| Operator | Bedeutung |
|---|---|
a ; b |
b läuft immer, egal wie a ausgeht |
a && b |
b läuft nur, wenn a Erfolg hatte (Status 0) |
a || b |
b läuft nur, wenn a fehlgeschlagen ist |
Hands-on:
mkdir /tmp/test && cd /tmp/test && pwdmkdir /tmp/test || echo "gibt es schon"cd ~ ; echo "bin wieder zuhause"sudo apt update && sudo apt upgrade -yDie letzte Zeile zeigt, warum && so beliebt ist: Das Upgrade soll nur laufen, wenn die Paketlisten erfolgreich geladen wurden. Mit ; würde es trotz Fehler starten.
Verschiedene Shells
Abschnitt betitelt „Verschiedene Shells“Die Bash ist nicht die einzige Shell, sondern nur die auf Linux üblichste:
| Shell | Pfad | Bemerkung |
|---|---|---|
Bourne Shell sh |
/bin/sh |
Das Original von 1979. Heute ein Verweis auf eine andere Shell. |
| Bash | /bin/bash |
«Bourne Again Shell», Standard auf fast allen Linux-Systemen. |
| Dash | /bin/dash |
Klein und schnell, auf Ubuntu und Debian steckt sie hinter /bin/sh. |
| Zsh | /bin/zsh |
Viele Komfortfunktionen, Standard auf macOS. |
| Fish | /usr/bin/fish |
Eigene, nicht POSIX-kompatible Syntax, sehr einsteigerfreundlich. |
Alle arbeiten nach denselben sechs Schritten, aber Syntax und Sonderzeichen unterscheiden sich im Detail. Wichtig für dich: Auf Ubuntu ist /bin/sh nicht die Bash, sondern Dash. Ein Skript mit #!/bin/sh darf darum nur das verwenden, was der POSIX-Standard vorschreibt. Bash-Spezialitäten wie [[ ]] oder Arrays funktionieren dort nicht. In diesem Kurs schreibst du Skripte deshalb immer mit #!/bin/bash.
Hands-on: Welche Shell läuft gerade?
echo "$SHELL"ps -p $$ls -l /bin/shcat /etc/shells$SHELL enthält deine Login-Shell, wie sie in /etc/passwd eingetragen ist. Das ist nicht zwingend die Shell, die gerade läuft. Verlässlich ist ps -p $$: $$ ist die Prozess-ID der aktuellen Shell, und ps zeigt dir, welches Programm dahintersteckt. Probiere es aus:
shps -p $$echo "$SHELL"exitIn der sh zeigt ps jetzt sh (eigentlich Dash), während $SHELL unverändert /bin/bash meldet. Mit exit bist du zurück in der Bash.
/bin/sh ist ein Symlink auf dash. Die Login-Shell neuer Benutzer ist /bin/bash, bei useradd ohne Optionen allerdings /bin/sh, deshalb adduser verwenden oder -s /bin/bash angeben.
/bin/sh ist ein Symlink auf bash, die sich im sh-Modus dann etwas strenger verhält. Ein Skript, das unter Fedora mit #!/bin/sh läuft, kann auf Ubuntu trotzdem scheitern.
Lösung anzeigen
type cd ls ll which type python3# Antwort 1: cd und type sind Builtins, ls und ll Aliase, which und python3 Programme in /usr/bin.echo "$PATH" | tr ':' '\n'echo "$PATH" | tr ':' '\n' | wc -l# Antwort 2: 9 Verzeichnisse (Standard-Ubuntu, plus ~/bin, wenn vorhanden).printf '#!/bin/bash\ndate +%%A\n' > ~/bin/wochentagchmod +x ~/bin/wochentagwochentagls /etc > /dev/null; echo $?ls /nirgends; echo $?# Antwort 4: 0 und 2.mkdir -p ~/labtest && cd ~/labtest && pwdshps -p $$exit# Antwort 6: In der Spalte CMD steht sh, dahinter steckt laut ls -l /bin/sh die Dash.Selbstcheck · 5 Fragen
Weiterführend
Abschnitt betitelt „Weiterführend“man bash, Abschnitt «COMMAND EXECUTION»- Bash Reference Manual: Shell Operation
- ubuntuusers Wiki: Shell