linux-cli-shell automation bash scripting error-handling advanced

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 -e und bauen eigene “Exception Handler” mittels trap. 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 pipefail am 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