Bash Error Handling & Exceptions (Artikel 251)
Strategien zur Fehlerbehandlung in Bash-Skripten. Erfahren Sie alles über Exit-Codes, die Absicherung durch set -e und die Implementierung robuster Fehlerroutinen.
# Error Handling: Skripte gegen das Scheitern härten
TL;DR / Management Summary Ein Skript, das bei einem Fehler einfach weitermacht, ist gefährlicher als gar kein Skript. In der professionellen Systemadministration ist Error Handling Pflicht. Wir nutzen Exit Codes, um den Erfolg von Befehlen zu prüfen, erzwingen den Abbruch bei Fehlern via
set -eund bauen eigene “Exception Handler” mittelstrap. Ein stabiles Skript erkennt Probleme, loggt sie und räumt hinter sich auf.
# 1. Einführung & Konzepte
Das Gesetz des Exit-Codes.
Jeder Linux-Befehl gibt beim Beenden eine Zahl zwischen 0 und 255 zurück.
- 0: Erfolg (Everything is fine).
- > 0: Fehler (Specific error code).
# Der Kontroll-Fluss (Mermaid)
graph TD
A[Command Execution] --> B{Exit Code $? == 0?}
B -->|Yes| C[Next Command]
B -->|No| D[Error Handling Routine]
D --> E[Log Error to Syslog]
D --> F[Cleanup Temp Files]
D --> G[Exit Script with Code 1]
# 2. Die automatische Notbremse: set -e
Kein Blindflug mehr.
Standardmäßig ignoriert Bash Fehler und führt die nächste Zeile aus.
#!/bin/bash
set -e # Abbruch bei erstem Fehler
set -u # Abbruch bei ungesetzten Variablen
set -o pipefail # Erkennt Fehler auch in Pipes
# 3. Custom Error Functions
Lesbare Fehlermeldungen.
Anstatt überall exit 1 zu schreiben, nutzen wir eine zentrale Funktion.
error_exit() {
local message="$1"
local code="${2:-1}"
echo "[ERROR] ${message}" >&2
logger -t "MY_SCRIPT" "CRITICAL: ${message}"
exit "$code"
}
# Nutzung:
cp config.txt /etc/app/ || error_exit "Konnte Konfiguration nicht kopieren"
# 4. Day-2 Operations: Cleanup mit trap
Den Tatort reinigen.
Wenn ein Skript abbricht, bleiben oft temporäre Dateien oder Locks zurück. trap fängt Signale ab und führt Aufräumarbeiten aus.
TMP_DIR=$(mktemp -d)
# Führe Cleanup bei EXIT (Normal oder Fehler) aus
trap 'rm -rf "$TMP_DIR"; echo "Cleanup done."' EXIT
# Skript Logik...
# 5. Troubleshooting & “War Stories”
Wenn die Fehlerbehandlung selbst zum Fehler wird.
# Story 1: “Der ignorierte Pipe-Fehler”
Symptom: Ein Backup-Skript meldet “Success”, obwohl die Disk voll war.
Ursache: cat /large/file | gzip > backup.gz. Wenn gzip scheitert, cat aber erfolgreich war, ist der Exit-Code der Pipe 0.
Lösung: Nutzen Sie set -o pipefail. Nur wenn alle Teile der Pipe erfolgreich waren, wird 0 zurückgegeben.
# Story 2: “set -e und bedingte Prüfungen”
Symptom: Ein Skript bricht ab, obwohl der “Fehler” beabsichtigt war (z.B. Prüfung ob Verzeichnis existiert).
Ursache: ls /non-existent-dir gibt Code 2 zurück. Mit set -e beendet sich das Skript sofort.
Lösung: Maskieren Sie Befehle, die scheitern dürfen:
ls /non-existent-dir || true oder nutzen Sie if Abfragen (diese werden von set -e ignoriert).
# 6. Fazit & Empfehlung
- Standard: Nutzen Sie immer
set -euo pipefailam Anfang Ihrer Skripte. - Logging: Schreiben Sie Fehlermeldungen immer nach stderr (
>&2), damit sie von Monitoring-Tools getrennt erfasst werden können. - Status: Geben Sie aussagekräftige Exit-Codes zurück (z.B. 1 für Dateifehler, 2 für Netzwerkfehler).
# Anhang: Cheatsheet
| Aufgabe | Befehl / Syntax |
|---|---|
| Letzten Exit Code prüfen | echo $? |
| Einfache Oder-Verknüpfung | `command |
| Und-Verknüpfung | command && success_action |
| Block-Grouping | `{ cmd1; cmd2; } |
| Signal abfangen | trap 'action' SIGNAL |
| Fehler simulieren | false (gibt immer 1 zurück) |
| Erfolg simulieren | true (gibt immer 0 zurück) |
| Script-Abbruch erzwingen | exit 1 |