Hohe CPU/RAM: Linux-Prozesse finden, analysieren und kontrollieren

Hohe CPU- oder RAM-Auslastung unter Linux systematisch debuggen: Prozesse mit top, htop, ps finden, mit kill/nice steuern, Speicherlecks aufspüren und OOM-Killer-Events analysieren.

9 min Lesezeit

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:

  1. uptime → Load Average interpretieren
  2. htop oder ps aux --sort=-%cpu → Schuldigen identifizieren
  3. ps -T -p PID → Threads analysieren
  4. strace -p PID -c → Was macht der Prozess?
  5. free -h → RAM-Situation
  6. journalctl -k | grep oom → OOM-Killer aktiv?

Die häufigsten Ursachen: Speicherleck (RAM), unkontrollierte Schleifen (CPU), hängende I/O-Operationen (hoher wa-Wert).

War dieser Artikel hilfreich?