Linux Troubleshooting-Flow: Systematisch Probleme lösen
Der Unterschied zwischen einem guten und einem schlechten Troubleshooter ist nicht das Wissen, sondern die Methode. Blindes Ausprobieren kostet Stunden. Ein strukturierter Ansatz – von der Symptom-Eingrenzung bis zur Ursachen-Analyse – löst die meisten Probleme in Minuten.
Dieser Guide ist dein Playbook für Linux-Problemsituationen.
Der universelle Troubleshooting-Flow
1. Situation erfassen
├── Was genau passiert? (Fehlermeldung?)
├── Wann hat es aufgehört zu funktionieren?
├── Was hat sich geändert?
└── Wer/was ist betroffen?
2. Logs analysieren
├── journalctl (systemd-Logs)
├── /var/log/ (klassische Logs)
└── Anwendungs-Logs
3. Ressourcen prüfen
├── Disk voll?
├── RAM erschöpft?
└── CPU überlastet?
4. Services und Prozesse
├── Service läuft?
├── Fehler-Exit-Code?
└── Abhängigkeiten?
5. Netzwerk
├── Verbindung?
├── DNS?
└── Port offen?
6. Lösung → Test → Dokumentation
Goldene Regel: Ändere immer nur eine Sache auf einmal. Sonst weißt du nicht, was geholfen hat.
Phase 1: Situation erfassen
Die wichtigsten ersten Fragen
# Wie lange läuft das System schon?
uptime
# 10:00:00 up 45 days, 3:20, ...
# Was ist die genaue Fehlermeldung?
# (immer vollständig kopieren, nicht umschreiben!)
# Wann hat das Problem begonnen?
# → Timestamp aus Logs
# → Wann war letztes Deployment, Update, Konfigurationsänderung?
# Letzte Systemänderungen anzeigen
last # Login-History
lastlog # letzter Login je User
journalctl --since "2 hours ago" -p warning
# Wer hat was geändert? (falls sudo geloggt wird)
grep "sudo" /var/log/auth.log | tail -30
journalctl _COMM=sudo --since "24 hours ago"
# Letzte Paket-Installationen/-Updates
grep " install \| upgrade " /var/log/dpkg.log | tail -20 # Ubuntu/Debian
dnf history | head -10 # Fedora
System-Schnellcheck
#!/bin/bash
# Systemstatus auf einen Blick
echo "=== SYSTEM STATUS ==="
echo "Hostname: $(hostname -f)"
echo "Zeit: $(date)"
echo "Uptime: $(uptime -p)"
echo ""
echo "=== RESSOURCEN ==="
df -h | grep -v "tmpfs\|udev"
free -h | grep "Mem:"
echo "Load: $(cut -d ' ' -f1-3 /proc/loadavg)"
echo ""
echo "=== FAILED SERVICES ==="
systemctl --failed --no-legend
echo ""
echo "=== LETZTE FEHLER ==="
journalctl -p err -b --no-pager -n 10
Phase 2: Logs analysieren
Das systemd-Journal: Erste Anlaufstelle
# Alle Fehler seit letztem Boot
journalctl -p err -b --no-pager
# Alle Logs live verfolgen
journalctl -f
# Logs seit einer Stunde
journalctl --since "1 hour ago" --no-pager
# Logs eines bestimmten Services
journalctl -u nginx -n 50 --no-pager
journalctl -u nginx -f # live
# Nur kritische Fehler
journalctl -p crit -b --no-pager
# Alle Fehler + Warnungen
journalctl -p warning -b --no-pager | head -50
Klassische Log-Dateien
# Wichtige Log-Pfade
/var/log/syslog # System-Messages (Ubuntu)
/var/log/messages # System-Messages (Fedora/RHEL)
/var/log/auth.log # Authentifizierung (Ubuntu)
/var/log/secure # Authentifizierung (Fedora)
/var/log/kern.log # Kernel-Logs
/var/log/apt/ # APT-History (Ubuntu)
/var/log/nginx/ # Nginx-Logs
/var/log/mysql/ # MySQL-Logs
/var/log/postgresql/ # PostgreSQL-Logs
# Live verfolgen
tail -f /var/log/nginx/error.log
# Nach Zeitstempel suchen
grep "Feb 18 10:" /var/log/syslog
# Fehler der letzten Stunde
grep "$(date -d '1 hour ago' '+%b %e %H')" /var/log/syslog | grep -i error
# Log-Analyse: häufigste Fehlermeldungen
awk '{print $6,$7,$8}' /var/log/nginx/error.log | sort | uniq -c | sort -rn | head -10
Log-Level-System
emerg (0) → System unbrauchbar
alert (1) → Sofortige Aktion nötig
crit (2) → Kritisch
err (3) → Fehler ← meist hier suchen
warn (4) → Warnung
note (5) → Hinweis
info (6) → Information
debug (7) → Debug (sehr viel Output)
Phase 3: Ressourcen prüfen (CPU, RAM, Disk)
Disk: Der häufigste stille Killer
# Ist Disk voll?
df -h
# Use% 100% oder 99% → Problem!
# Welches Verzeichnis ist groß?
du -sh /* 2>/dev/null | sort -rh | head -10
ncdu / # interaktiv
# Inodes voll? (Dateien obwohl Disk "voll" zeigt 0)
df -i
# IUse% 100% → Inode-Problem
# Gelöschte aber noch offene Dateien (unsichtbarer Speicher!)
sudo lsof | grep deleted | awk '{print $1, $7}' | sort -k2 -rn | head -10
RAM: Knappheit erkennen
# RAM-Status
free -h
# "available" ist die wichtige Zahl (nicht "free")
# Swap-Nutzung
free -h | grep Swap
# Wenn Swap > 50% genutzt: Speicherproblem
# Speicherhungrige Prozesse
ps aux --sort=-%mem | head -10
# OOM-Killer war aktiv?
journalctl -k | grep -i "oom\|killed process"
dmesg | grep -i "oom\|killed"
CPU: Last einschätzen
# Systemlast
uptime
# load average: 12.5, 8.3, 5.2
# Auf einem 4-Kern-System: > 4 = Überlast
# CPU-Fresser finden
ps aux --sort=-%cpu | head -10
top -bn1 | head -15
# I/O-Wait (CPU wartet auf Disk)
iostat -x 1 3 # wenn %iowait > 20%: I/O-Bottleneck
Phase 4: Services und Prozesse prüfen
Service-Status-Workflow
# 1. Service-Status
sudo systemctl status nginx
# Typische Ausgaben:
# Active: active (running) → OK
# Active: failed → Fehler! Exit-Code prüfen
# Active: inactive (dead) → Service nicht gestartet
# Active: activating → Startet noch...
# 2. Warum ist der Service fehlgeschlagen?
journalctl -u nginx -n 50 --no-pager
# 3. Service manuell starten und Fehler sehen
sudo systemctl start nginx
sudo journalctl -u nginx -f # in zweitem Terminal
# 4. Alle fehlgeschlagenen Services
systemctl --failed
# 5. Abhängigkeiten prüfen
systemctl list-dependencies nginx.service
Service startet nicht: Checklist
# a) Konfigurationsdatei korrekt?
sudo nginx -t # nginx
sudo apache2ctl configtest # apache
# b) Port bereits belegt?
sudo ss -tlnp | grep :80
# c) Berechtigungen korrekt?
ls -la /etc/nginx/nginx.conf # gehört root?
ls -la /var/www/html/ # gehört www-data?
# d) ExecStart-Pfad existiert?
sudo systemctl cat nginx | grep ExecStart
ls -la /usr/sbin/nginx
# e) Umgebungsvariablen gesetzt?
sudo systemctl cat mein-service | grep EnvironmentFile
sudo cat /etc/mein-service/environment
# f) Service manuell als Service-User starten
sudo -u www-data /usr/sbin/nginx -g "daemon off;" -c /etc/nginx/nginx.conf
Phase 5: Netzwerk und Konnektivität
Schicht für Schicht debuggen
# Layer 1/2: Interface vorhanden und aktiv?
ip link
# eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ← UP = ok
# Layer 3: IP vorhanden?
ip addr
# 192.168.1.100/24 auf eth0 ← ok
# Layer 3: Route vorhanden?
ip route
# default via 192.168.1.1 ← Default-Gateway ok
# Layer 3: Gateway erreichbar?
ping -c4 $(ip route | awk '/default/ {print $3}')
# Layer 3: Internet erreichbar?
ping -c4 8.8.8.8
# Layer 7: DNS funktioniert?
dig google.com +short @8.8.8.8
nslookup google.com
# Layer 4: Port offen?
sudo ss -tlnp | grep :80
# Layer 7: HTTP-Request klappt?
curl -I http://localhost
curl -I https://meine-seite.de
Netzwerkprobleme: Typische Szenarien
# "kein Internet, aber LAN ok"
ping 8.8.8.8 # klappt? → DNS-Problem
dig google.com @8.8.8.8 # direkt → lokaler DNS kaputt
# "Port offen, aber keine Verbindung"
sudo ufw status # Firewall?
sudo iptables -L | grep DROP # iptables-Regeln?
# "DNS schlägt fehl"
cat /etc/resolv.conf # welcher DNS-Server?
resolvectl status # systemd-resolved
# DNS-Cache leeren
sudo resolvectl flush-caches
# "Verbindung bricht ab"
mtr --report server # Packet-Loss auf Route?
ping -c100 server | tail -3 # Paketverlust?
Phase 6: Änderungen rückgängig machen
# Paket auf alte Version zurückrollen (apt)
apt list --installed nginx # aktuelle Version
sudo apt-get install nginx=1.24.0-2 # alte Version erzwingen
sudo apt-mark hold nginx # Version einfrieren
# Konfigurationsdatei zurücksetzen
sudo cp /etc/nginx/nginx.conf.backup /etc/nginx/nginx.conf
sudo systemctl restart nginx
# Timeshift-Snapshot zurückrollen (System)
sudo timeshift --restore
# Docker-Container auf altes Image zurückrollen
docker pull meine-app:v1.2.3
docker-compose up -d # nach Image-Tag-Änderung in compose.yaml
# Git: Code-Stand zurücksetzen
git log --oneline -10 # welcher Commit war gut?
git checkout COMMIT_HASH -- src/ # nur bestimmte Dateien
git revert COMMIT_HASH # sauber rückgängig machen
# Datenbankstand (wenn Dump vorhanden)
mysql -u root -p meinedatenbank < backup_20260217.sql
Häufige Problem-Szenarien
Szenario 1: Webseite antwortet nicht (502 Bad Gateway)
# 1. Ist nginx aktiv?
sudo systemctl status nginx
# Active: active ← nginx läuft
# 2. Was sagen nginx-Logs?
sudo tail -50 /var/log/nginx/error.log
# 502 connect() failed ... php8.4-fpm.sock
# 3. Ist PHP-FPM aktiv?
sudo systemctl status php8.4-fpm
# Active: failed ← PHP-FPM ist kaputt!
# 4. Warum ist PHP-FPM kaputt?
journalctl -u php8.4-fpm -n 30 --no-pager
# "no space left on device" ← Disk voll!
# 5. Disk prüfen und freigaben
df -h
sudo journalctl --vacuum-time=7days
sudo apt clean
# 6. PHP-FPM neu starten
sudo systemctl start php8.4-fpm
curl -I http://localhost # Test
Szenario 2: Server reagiert sehr langsam
# 1. Systemlast prüfen
uptime
# load: 45.3, 38.7, 28.2 auf 8-Kern-System → massiv überlastet
# 2. CPU-Fresser finden
ps aux --sort=-%cpu | head -5
# www 12345 99.9 15.2 ... php-fpm
# 3. I/O-Wait prüfen
iostat -x 1 3
# %iowait = 85% → Disk ist Flaschenhals
# 4. Disk-I/O prüfen
iotop # interaktiv (sudo apt install iotop)
# oder:
iostat -dx 1 3
# 5. Hängende Prozesse finden
ps aux | awk '$8 == "D"' | head -10
# D-State = wartet auf I/O
# 6. Was schreibt auf die Disk?
sudo lsof | awk '$5 == "REG" && $6 > 100000000' | sort -k6 -rn | head -10
Szenario 3: Service startet nicht nach Neustart
# 1. Service-Logs
journalctl -u mein-service -b --no-pager
# "EnvironmentFile: no such file or directory"
# 2. Fehlende Datei erstellen
sudo nano /etc/mein-service/environment
# 3. Oder: Permission-Problem?
ls -la /var/lib/mein-service/
# drwx------ root root ← www-data hat keinen Zugriff!
sudo chown -R www-data:www-data /var/lib/mein-service/
# 4. Service neu starten
sudo systemctl start mein-service
sudo systemctl status mein-service
# 5. Nächsten Boot prüfen (wenn möglich)
# systemd-analyze blame ← Boot-Zeit-Analyse
# systemctl list-units --failed ← nach Neustart
Troubleshooting-Checkliste
TROUBLESHOOTING CHECKLISTE
══════════════════════════
☐ Fehlermeldung vollständig notiert (exakter Wortlaut)
☐ Zeitpunkt des Auftretens bekannt
☐ Letzte Änderungen identifiziert:
☐ Updates: grep "upgrade\|install" /var/log/dpkg.log | tail -20
☐ Konfigurationsänderungen: git log -20 (falls versioniert)
☐ Deployments: Deployment-Log prüfen
Logs gecheckt:
☐ journalctl -p err -b
☐ journalctl -u SERVICE -n 50
☐ Anwendungs-spezifische Logs in /var/log/
Ressourcen gecheckt:
☐ df -h → Disk nicht voll?
☐ free -h → RAM ausreichend?
☐ uptime → Last normal?
☐ sudo lsof | grep deleted (Ghosts?)
Services gecheckt:
☐ systemctl --failed
☐ sudo systemctl status SERVICE
☐ Konfiguration korrekt?
Netzwerk gecheckt:
☐ ip addr → IP vorhanden?
☐ ping gateway → Gateway erreichbar?
☐ ping 8.8.8.8 → Internet erreichbar?
☐ dig domain.de → DNS funktioniert?
Änderung gemacht:
☐ NUR eine Änderung auf einmal
☐ Änderung dokumentiert
☐ Test nach Änderung
☐ Monitoring danach
Fazit
Systematisches Troubleshooting spart Zeit und Nerven. Der Schlüssel liegt darin, nicht zu raten, sondern von den Symptomen zur Ursache zu navigieren:
- Logs sind dein bester Freund –
journalctl -p err -bals erstes - Disk full ist häufiger als gedacht – immer früh
df -hprüfen - Eine Änderung auf einmal – sonst weißt du nicht, was geholfen hat
- Dokumentiere die Lösung – für den nächsten Vorfall
Die meisten Linux-Probleme sind in einer der fünf Kategorien: Disk voll, Service crashed, Rechte falsch, Netzwerk broken, Konfigurationsfehler.