EMZETT.
Login

Kurz: Standardmäßig läuft Bash bei Fehlern einfach weiter, auch wenn ein Befehl scheitert oder eine Variable leer ist. Das ist gefährlich. Üblicher Skript-Kopf:

Teil des Kurses Bash

Kapitel 10 von 13 im Kurs Bash (Abschnitt „Fortgeschritten“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Der “Strict Mode”

Standardmäßig läuft Bash bei Fehlern einfach weiter, auch wenn ein Befehl scheitert oder eine Variable leer ist. Das ist gefährlich. Üblicher Skript-Kopf:

#!/usr/bin/env bash
set -euo pipefail
OptionWirkung
-eSkript bricht beim ersten fehlgeschlagenen Befehl ab
-uVerwendung nicht gesetzter Variablen ist ein Fehler
-o pipefailEine Pipe schlägt fehl, wenn irgendein Teil fehlschlägt
bash -c '
set -e
echo "Anfang"
false
echo "wird nie erreicht"
'; echo "Status: $?"
 
bash -c '
set -u
echo "vor der Variable"
echo "$nicht_gesetzt"
' 2>&1 | head -3
 
bash -c 'set -u; echo "mit Standardwert: ${var:-standard}"'
bash -c 'set -e; false || echo "|| fängt den Fehler ab"; echo "weiter"'

Ausgabe:

Anfang
Status: 1
vor der Variable
bash: line 4: nicht_gesetzt: unbound variable
mit Standardwert: standard
|| fängt den Fehler ab
weiter

Hinweis

set -e hat Sonderfälle (z. B. in if-Bedingungen oder bei ||). Verlasse dich nicht blind darauf, sondern prüfe wichtige Schritte ausdrücklich.

Fehler prüfen und melden

fehler() { echo "FEHLER: $*" >&2; }
abbruch() { fehler "$@"; return 1; }
 
kopiere() {
    local quelle=$1 ziel=$2
    [[ -f $quelle ]] || { abbruch "Quelle '${quelle##*/}' fehlt"; return 1; }
    cp "$quelle" "$ziel"
}
 
d=$(mktemp -d)
echo x > "$d/a"
kopiere "$d/a" "$d/b" && echo "kopiert"
kopiere "$d/nix" "$d/c" 2>&1 || echo "kopiere scheiterte (Status $?)"
 
if ! ls "$d/nix" >/dev/null 2>&1; then
    echo "Datei nicht vorhanden"
fi

Ausgabe:

kopiert
FEHLER: Quelle 'nix' fehlt
kopiere scheiterte (Status 1)
Datei nicht vorhanden

trap: aufräumen und Fehler fangen

trap führt Code bei Signalen oder am Ende aus. Typisch: temporäre Dateien löschen, egal wie das Skript endet.

tmp=$(mktemp -d)
aufraeumen() {
    rm -rf "$tmp"
    echo "aufgeräumt"
}
trap aufraeumen EXIT
 
echo "arbeite in einem temporären Ordner"
[[ -d $tmp ]] && echo "Ordner existiert"

Ausgabe:

arbeite in einem temporären Ordner
Ordner existiert
aufgeräumt
bash -c '
set -e
trap '"'"'echo "Fehler in Zeile $LINENO"'"'"' ERR
echo "läuft"
ls /gibt/es/nicht 2>/dev/null
echo "nie erreicht"
'; echo "Status: $?"

Ausgabe:

läuft
Fehler in Zeile 5
Status: 2

Gängige Signale: EXIT (immer am Ende), ERR (Befehl scheitert), INT (Strg+C), TERM (Beenden-Anfrage).

Eingaben validieren

nur_zahl() {
    [[ $1 =~ ^-?[0-9]+$ ]]
}
for wert in 42 -7 4x "" 3.5; do
    if nur_zahl "$wert"; then echo "[$wert] ist eine Ganzzahl"; else echo "[$wert] keine Zahl"; fi
done
 
pruefe_argumente() {
    (( $# == 2 )) || { echo "Aufruf: skript QUELLE ZIEL" >&2; return 2; }
    echo "OK: $1 -> $2"
}
pruefe_argumente a b
pruefe_argumente a || echo "Status $?"

Ausgabe:

[42] ist eine Ganzzahl
[-7] ist eine Ganzzahl
[4x] keine Zahl
[] keine Zahl
[3.5] keine Zahl
OK: a -> b
Status 2

Sicherer Umgang mit Dateien und Variablen

  • Immer "$variable" quoten
  • Mit -- das Ende der Optionen markieren: rm -- "$datei" (Dateinamen mit - am Anfang)
  • Temporäre Dateien nur mit mktemp anlegen
  • Vor rm -rf die Variable prüfen: rm -rf "${ordner:?}/" bricht ab, wenn ordner leer ist
  • Befehle auf Existenz prüfen: command -v jq >/dev/null || { echo "jq fehlt"; exit 1; }
  • Skripte mit ShellCheck (shellcheck.net) analysieren
ordner=""
bash -c 'ordner=""; echo rm -rf "${ordner:?Variable leer}/"' 2>&1 | head -1
command -v bash >/dev/null && echo "bash gefunden"
command -v programm_gibts_nicht >/dev/null || echo "programm fehlt"
echo "--" ; touch -- "-komischer-name" && ls -- -komischer-name && rm -- -komischer-name

Ausgabe:

bash: line 1: ordner: Variable leer
bash gefunden
programm fehlt
--
-komischer-name

Debugging

bash -x -c 'x=5; y=$((x * 2)); echo "$y"' 2>&1 | head -5

Ausgabe:

+ x=5
+ y=10
+ echo 10
10

set -x zeigt jeden ausgeführten Befehl, set +x schaltet es wieder ab. bash -n skript.sh prüft nur die Syntax. Zusätzlich helfen echo-Ausgaben nach stderr und PS4='+ ${LINENO}: '.

Merke

  • Skript-Kopf: #!/usr/bin/env bash und set -euo pipefail
  • Fehlermeldungen nach stderr (>&2), sinnvolle Exit-Codes
  • trap ... EXIT räumt zuverlässig auf
  • Eingaben validieren, Variablen quoten, -- vor Dateinamen
  • shellcheck, bash -n und set -x helfen beim Debuggen

Übungsaufgabe

Schreibe ein Skript, das einen Ordner sichert (tar), temporäre Dateien per trap löscht und bei fehlendem Argument sauber abbricht.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Dateisystem, Navigation und Rechte

Weiter: Prozesse, Cron, SSH und Pakete

Alle Kapitel: Bash im Überblick