Hohe CPU/RAM: Linux-Prozesse finden, analysieren und kontrollieren
Server-CPU bei 100%? Swap voll? OOM-Killer erschlägt Prozesse? In diesen Momenten zählt Geschwindigkeit. Wer die richtigen Tools kennt und einen klaren Diagnose-Flow hat, findet den Schuldigen in Minuten – nicht Stunden.
Schnelldiagnose: Wer frisst was?
# Top 5 CPU-Fresser
ps aux --sort=-%cpu | head -6
# Top 5 RAM-Fresser
ps aux --sort=-%mem | head -6
# Systemlast auf einen Blick
uptime
# 10:00:00 up 5 days, 2:30, 2 users, load average: 0.85, 1.20, 1.45
# 1min 5min 15min
# Alle Ressourcen auf einmal
vmstat 1 5 # 5 Ausgaben im 1-Sekunden-Interval
Systemlast (Load Average) interpretieren
load average: 1.20, 0.85, 0.90
↑ ↑ ↑
1 Min 5 Min 15 Min
# Faustregeln:
# < Anzahl CPU-Kerne = OK
# = Anzahl CPU-Kerne = ausgelastet
# > Anzahl CPU-Kerne = Überlast (Prozesse warten auf CPU)
# Anzahl CPU-Kerne anzeigen
nproc
# Load von 4.0 auf einem 4-Kern-System = 100% ausgelastet
# Load von 4.0 auf einem 8-Kern-System = 50% ausgelastet
top und htop: Interaktives Monitoring
top
# top starten
top
# Wichtige Tastenbefehle in top:
# q : Beenden
# k : Prozess killen (PID eingeben)
# r : nice-Wert ändern (renice)
# M : Nach RAM sortieren
# P : Nach CPU sortieren (Standard)
# T : Nach Laufzeit sortieren
# 1 : CPU-Kerne einzeln anzeigen
# H : Threads anzeigen
# u : Nach Benutzer filtern
# c : Vollständigen Befehl anzeigen
# i : Idle-Prozesse ausblenden
# e : RAM-Einheit wechseln (k/m/g)
# top einmalig (kein interaktiv)
top -bn1 | head -20
# top für spezifischen Benutzer
top -u www-data
# top für spezifischen Prozess
top -p 1234
top-Ausgabe verstehen
Tasks: 142 total, 2 running, 140 sleeping
%Cpu(s): 8.5 us, 1.2 sy, 0.0 ni, 89.3 id, 0.5 wa, 0.0 hi, 0.5 si
MiB Mem: 7850.5 total, 1234.2 free, 4567.8 used, 2048.5 buff/cache
MiB Swap: 2048.0 total, 1987.3 free, 60.7 used. 3048.2 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1234 www-data 20 0 512m 234m 45m R 85.3 2.98 15:32.1 php-fpm
5678 mysql 20 0 4567m 1234m 256m S 5.2 15.72 45:23.4 mariadbd
us = User-Space-CPU (Anwendungen)
sy = Kernel-Space-CPU (Syscalls)
wa = I/O-Wait (Warten auf Festplatte/Netzwerk)
id = Idle (ungenutzte CPU)
VIRT = Virtueller Speicher (inkl. gemappte Dateien)
RES = Physischer RAM (tatsächlich genutzt)
SHR = Geteilter Speicher
S = Status: R=Running, S=Sleeping, Z=Zombie, D=I/O-Wait
htop (empfohlen)
# Installieren
sudo apt install htop # Ubuntu/Debian
sudo dnf install htop # Fedora
# Starten
htop
# Wichtige Features:
# F2/S : Einstellungen (Farben, Columns)
# F3 : Suchen nach Prozessname
# F4 : Filtern
# F5 : Tree-Ansicht (Parent-Child-Hierarchie)
# F6 : Sortierung wählen
# F9 : Prozess killen (mit Signal-Auswahl)
# Space : Prozess markieren (Mehrfachauswahl)
# u : Nach User filtern
# t : Baum-Ansicht umschalten
ps: Prozess-Snapshots
# Alle Prozesse (BSD-Stil, am häufigsten)
ps aux
# Alle Prozesse (UNIX-Stil)
ps -ef
# Spezifischer Prozess
ps aux | grep nginx
ps -C nginx # nach Prozessname
# Nur meine Prozesse
ps
# Baumansicht
ps auxf # forest/tree
pstree # alternativ
# Prozesse sortiert nach CPU
ps aux --sort=-%cpu | head -10
# Prozesse sortiert nach RAM
ps aux --sort=-%mem | head -10
# Spezifische Felder
ps -o pid,ppid,user,%cpu,%mem,cmd -C nginx
# Alle Threads eines Prozesses
ps -T -p 1234
# Lange Ausführungszeit
ps aux --sort=-etime | head -10
ps-Ausgabe verstehen
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
www-data 1234 8.5 2.9 524288 240128 ? Ss 10:00 0:15 php-fpm
STAT-Codes:
R = Running
S = Sleeping (interruptible)
D = Sleeping (uninterruptible, I/O-Wait) ← Problem!
Z = Zombie
T = Stopped (Hintergrund, SIGSTOP)
< = Hohe Priorität
N = Niedrige Priorität
+ = Vordergrundprozess
Prozesse steuern: kill, nice, renice
kill: Signale senden
# PID herausfinden
pidof nginx
pgrep nginx
pgrep -l nginx # mit Namen
# SIGTERM senden (sanftes Beenden, Standard)
kill 1234
kill -15 1234 # explizit SIGTERM
kill -TERM 1234 # gleichwertig
# SIGKILL (sofort beenden, kein Cleanup)
kill -9 1234
kill -KILL 1234
# SIGHUP (neu laden, für Daemons)
kill -HUP 1234
kill -1 1234
# Nach Name beenden
pkill nginx # alle nginx-Prozesse
pkill -9 nginx # sofortig
pkill -u www-data # alle Prozesse von www-data
# Interaktiv (mit Bestätigung)
pkill -i nginx
# killall: nach Name (etwas sicherer)
killall nginx
# Signal-Übersicht
kill -l
Signale verstehen
| Signal | Nummer | Bedeutung | Wann nutzen |
|---|---|---|---|
| SIGHUP | 1 | Reload-Konfiguration | Service neu laden |
| SIGINT | 2 | Interrupt (Ctrl+C) | Interaktive Unterbrechung |
| SIGTERM | 15 | Sanftes Beenden | Normaler Stop |
| SIGKILL | 9 | Sofort töten | Hängende Prozesse |
| SIGUSR1 | 10 | Benutzerdefiniert | App-spezifisch |
| SIGUSR2 | 12 | Benutzerdefiniert | App-spezifisch |
nice und renice: Priorität steuern
# Prozess mit niedrigerer Priorität starten (1-19, höher = weniger Priorität)
nice -n 10 ./schwere-berechnung.sh
nice -n 19 ./backup-skript.sh # Niedrigste Priorität für Batch-Jobs
# Laufenden Prozess priorisieren
renice -n 5 -p 1234 # Prozess mit PID 1234
renice -n -5 -p 1234 # Höhere Priorität (braucht root!)
sudo renice -n -10 -p 1234
# Alle Prozesse eines Users
renice -n 10 -u www-data
# nice-Wert anzeigen
ps -o pid,ni,cmd -p 1234
Prozesse im Hintergrund
# Im Hintergrund starten
./langes-skript.sh &
# Vordergrundprozess in Hintergrund schicken
Ctrl+Z # Prozess anhalten
bg # im Hintergrund weiterlaufen lassen
# Hintergrundprozesse anzeigen
jobs
# Hintergrundprozess in Vordergrund holen
fg %1 # %1 = Job-Nummer
# Prozess auch nach Logout weiterführen (nohup)
nohup ./langes-skript.sh &
# besser: screen oder tmux
screen -S meine-session
tmux new -s meine-session
RAM-Analyse: Speicher verstehen
free: RAM-Überblick
# RAM-Status
free -h
# total used free shared buff/cache available
# Mem: 7.7G 4.2G 1.1G 234M 2.4G 3.1G
# Swap: 2.0G 512M 1.5G
# Alle 2 Sekunden aktualisieren
free -h -s 2
# In Megabyte
free -m
available ist die wichtige Zahl! – Nicht free. available zeigt den Speicher, der für neue Prozesse verfügbar ist (inkl. reclaimable Buffers/Cache).
Detaillierte RAM-Analyse
# Kernel-Speicher-Details
cat /proc/meminfo
# Wichtige Felder:
grep -E "MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree|Cached|Buffers|Slab" \
/proc/meminfo
# Shared Memory
ipcs -m # System V Shared Memory
# Huge Pages (für Datenbanken)
grep HugePages /proc/meminfo
RAM-Verbrauch pro Prozess
# Alle Prozesse nach RAM sortiert
ps aux --sort=-%mem | head -15
# Detaillierter RAM-Report für Prozess
cat /proc/1234/status | grep -i "vm"
# VmPeak: 512 MB (maximaler virtueller Speicher)
# VmRSS: 234 MB (resident set size = tatsächlicher RAM)
# VmSwap: 0 MB (genutzter Swap)
# smem: Akkurater RAM-Report (teilt shared memory korrekt auf)
sudo apt install smem
smem -r -k | head -20
# pmap: Speicher-Map eines Prozesses
pmap -x 1234 | tail -3
Swap-Analyse
# Swap-Nutzung
swapon --summary
cat /proc/swaps
# Prozesse mit Swap-Nutzung (braucht root)
for f in /proc/*/status; do
pid=$(echo $f | cut -d/ -f3)
swap=$(awk '/VmSwap/{print $2}' $f 2>/dev/null)
[ -n "$swap" ] && [ "$swap" -gt 0 ] && \
echo "$swap kB PID=$pid $(cat /proc/$pid/comm 2>/dev/null)"
done | sort -rn | head -10
# Swappiness: Tendenz zum Auslagern (0=wenig, 100=viel)
cat /proc/sys/vm/swappiness
# Standard: 60
# Für Server: niedrigere swappiness empfohlen
sudo sysctl vm.swappiness=10
# Dauerhaft in /etc/sysctl.d/99-performance.conf:
echo "vm.swappiness=10" | sudo tee /etc/sysctl.d/99-performance.conf
OOM-Killer: Was passiert wenn RAM voll ist?
Wenn RAM und Swap erschöpft sind, aktiviert der Linux-Kernel den OOM-Killer (Out-of-Memory Killer) und beendet Prozesse.
OOM-Events erkennen
# In Kernel-Logs suchen
sudo journalctl -k | grep -i "oom\|out of memory\|killed process"
sudo dmesg | grep -i "oom\|killed"
# Typische OOM-Log-Ausgabe:
# kernel: Out of memory: Kill process 1234 (mysql) score 812 or sacrifice child
# kernel: Killed process 1234 (mysql) total-vm:4567MB, anon-rss:2345MB
OOM-Score verstehen
# OOM-Score eines Prozesses (0-1000, höher = eher zu killen)
cat /proc/1234/oom_score
# OOM-Score-Anpassung (-1000 bis 1000)
# Höherer Wert = wahrscheinlicher zu killen
cat /proc/1234/oom_score_adj
# Wichtigen Prozess vor OOM schützen (nur root)
echo -1000 | sudo tee /proc/1234/oom_score_adj
# Dauerhaft: in systemd-Service
sudo systemctl edit mein-service
[Service]
OOMScoreAdjust=-900 # Sehr unwahrscheinlich zu killen
# oder:
OOMPolicy=continue # Service ignoriert OOM (gefährlich!)
OOM-Probleme lösen
# Sofortmaßnahme: Speicher freigeben
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches
# 1=pagecache, 2=dentries+inodes, 3=alles
# Swap leeren (Daten werden in RAM verschoben)
sudo swapoff -a && sudo swapon -a
# Langfristig: Mehr Swap erstellen
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
CPU-Analyse: Lastspitzen finden
# CPU-Frequenz und -Kerne
nproc # Anzahl Kerne
lscpu # CPU-Details
cat /proc/cpuinfo | grep "model name" | head -1
# I/O-Wait diagnostizieren (häufige Ursache für hohe Last)
iostat -x 1 5 # Extended I/O-Statistik
# sudo apt install sysstat
# Wenn %iowait hoch: Disk oder Netzwerk
# Normal: < 5%
# Problem: > 20%
# welche Prozesse warten auf I/O?
ps aux | awk '$8 == "D"' | head -20 # D = uninterruptible sleep (I/O)
# CPU-Profiling mit perf
sudo apt install linux-perf
sudo perf top # Live CPU-Profiling
sudo perf stat -a sleep 10 # 10 Sekunden CPU-Statistik
# strace: Syscalls eines Prozesses verfolgen
sudo strace -p 1234 -c # Syscall-Statistik (-c = count)
sudo strace -p 1234 -e trace=network # nur Netzwerk-Syscalls
lsof: Offene Dateien und Verbindungen
# Alle offenen Dateien
sudo lsof | head -20
# Dateien eines Prozesses
sudo lsof -p 1234
# Wer hat eine Datei offen?
sudo lsof /var/log/nginx/access.log
# Welche Dateien hat ein User offen?
lsof -u www-data
# Netzwerkverbindungen
sudo lsof -i # alle
sudo lsof -i :80 # auf Port 80
sudo lsof -i TCP:443 # TCP Port 443
sudo lsof -i @192.168.1.1 # zu/von IP
# Gelöschte Dateien die noch offen sind (Speicherproblem!)
sudo lsof | grep deleted | sort -k7 -rn | head -10
# Prozess neu starten um Speicher freizugeben
Automatisches Monitoring
Schnelles Alert-Skript
sudo nano /usr/local/bin/resource-check.sh
#!/bin/bash
THRESHOLD_CPU=80
THRESHOLD_MEM=90
HOSTNAME=$(hostname)
# CPU-Auslastung (1-Minuten-Durchschnitt)
LOAD=$(cut -d ' ' -f1 /proc/loadavg)
CPUS=$(nproc)
CPU_PCT=$(awk "BEGIN {printf \"%.0f\", ($LOAD/$CPUS)*100}")
# RAM-Auslastung
RAM_TOTAL=$(free -m | awk '/Mem:/ {print $2}')
RAM_USED=$(free -m | awk '/Mem:/ {print $3}')
RAM_PCT=$((RAM_USED * 100 / RAM_TOTAL))
ALERT=""
if [ "$CPU_PCT" -gt "$THRESHOLD_CPU" ]; then
TOP_PROC=$(ps aux --sort=-%cpu | awk 'NR==2 {print $11, $3"%"}')
ALERT+="CPU bei ${CPU_PCT}% (Top: $TOP_PROC)\n"
fi
if [ "$RAM_PCT" -gt "$THRESHOLD_MEM" ]; then
TOP_PROC=$(ps aux --sort=-%mem | awk 'NR==2 {print $11, $4"%"}')
ALERT+="RAM bei ${RAM_PCT}% (Top: $TOP_PROC)\n"
fi
if [ -n "$ALERT" ]; then
echo -e "ALERT auf $HOSTNAME:\n$ALERT" | \
mail -s "Resource Alert: $HOSTNAME" admin@example.com
fi
chmod +x /usr/local/bin/resource-check.sh
# Alle 5 Minuten prüfen:
echo "*/5 * * * * root /usr/local/bin/resource-check.sh" | \
sudo tee /etc/cron.d/resource-check
Fazit
Hohe CPU/RAM-Last ist fast immer auf einen einzelnen Prozess oder eine Prozessgruppe zurückzuführen. Der Diagnose-Flow:
uptime→ Load Average interpretierenhtopoderps aux --sort=-%cpu→ Schuldigen identifizierenps -T -p PID→ Threads analysierenstrace -p PID -c→ Was macht der Prozess?free -h→ RAM-Situationjournalctl -k | grep oom→ OOM-Killer aktiv?
Die häufigsten Ursachen: Speicherleck (RAM), unkontrollierte Schleifen (CPU), hängende I/O-Operationen (hoher wa-Wert).