Anleitung

Prozesse in Linux: ps, top, htop, kill, Signale und nice

Aktualisiert: · Skillaria.Top

Prozesse in Linux betrachten Sie mit ps aux (einmalige Momentaufnahme), top und htop (aktualisierte Liste mit Last). Beendet wird ein Prozess mit kill PID, das standardmäßig das höfliche SIGTERM sendet; kill -9 (SIGKILL) brauchen Sie nur, wenn der Prozess nicht reagiert. Die Priorität legen Sie beim Start mit nice fest und ändern sie bei laufenden Prozessen mit renice, im Bereich von -20 bis 19.

Jedes laufende Programm in Linux ist ein Prozess mit eigener PID-Nummer, einem Besitzer, einem Zustand und einer Priorität. Prozesse betrachten Sie mit ps, top und htop, beenden mit kill und ihre Priorität ändern Sie mit nice und renice. Im Folgenden lernen Sie, die Ausgabe dieser Befehle zu lesen, welches Signal wann passt und warum kill -9 nicht der erste Reflex sein sollte.

Was ein Prozess und eine PID sind

Ein Prozess ist ein Programm während der Ausführung: Code, Speicher, geöffnete Dateien und eine Reihe von Attributen. Der Kernel vergibt an jeden Prozess eine eindeutige Kennung, die PID, und merkt sich zusätzlich die PPID, also die Nummer des Elternprozesses, der ihn gestartet hat. Der allererste Prozess im System mit der PID 1 ist meist systemd. Er ist der Vorfahre aller übrigen Prozesse.

Ein neuer Prozess entsteht in zwei Schritten. Zuerst ruft der Elternprozess fork() auf und erhält eine eigene Kopie. Dann ersetzt die Kopie mit execve() ihren Code durch den Code des neuen Programms. Wenn Sie im Terminal ls eintippen, macht bash genau das und wartet mit wait() auf das Ende des Kindprozesses.

$ echo $$          # PID der aktuellen Shell
4182
$ ps -o pid,ppid,cmd -p $$
    PID    PPID CMD
   4182    4170 -bash

Prozesse mit dem Befehl ps anzeigen

ps erstellt eine einmalige Momentaufnahme: Es zeigt die Prozesse genau zum Zeitpunkt des Aufrufs an und endet danach. Ohne Argumente zeigt es nur die Prozesse des aktuellen Terminals. In der Praxis verwendet man deshalb fast immer eine von zwei Varianten.

$ ps aux | head -5
USER       PID %CPU %MEM    VSZ   RSS TTY   STAT START   TIME COMMAND
root         1  0.0  0.3 168540 12780 ?     Ss   09:12   0:03 /sbin/init
root         2  0.0  0.0      0     0 ?     S    09:12   0:00 [kthreadd]
www-data  1532  1.2  2.1 412308 86420 ?     S    09:15   1:47 php-fpm: pool www
postgres  1610  0.4  3.8 221004 154312 ?    Ss   09:15   0:31 postgres: checkpointer

Dabei steht a für die Prozesse aller Benutzer, u für das ausführliche Format mit Besitzer und x für Prozesse ohne Terminal (Dämonen). Die Syntax im Stil von System V lautet ps -ef. Sie zeigt die PPID, was hilfreich ist, wenn Sie herausfinden wollen, wer wen gestartet hat.

SpalteBedeutung
PIDKennung des Prozesses
%CPU, %MEMAnteil am Prozessor und am physischen Speicher
VSZvirtueller Speicher in KB (auch das, was nicht im RAM liegt)
RSStatsächlich belegter physischer Speicher in KB
STATZustand des Prozesses (R, S, D, Z, T) und Zusatzzeichen
TIMEinsgesamt verbrauchte Prozessorzeit, nicht die Laufzeit

Nützliche Tricks mit ps

# Top 10 nach Speicher
ps aux --sort=-%mem | head -11

# Top 10 nach Prozessor
ps aux --sort=-%cpu | head -11

# eigene Spalten
ps -eo pid,ppid,user,ni,stat,etime,cmd

# Prozessbaum
ps -ef --forest
pstree -p

# PID anhand des Namens finden
pgrep -a nginx
pidof nginx

Ein typischer Fehler ist die Suche mit ps aux | grep nginx. Dabei taucht in der Ausgabe auch der grep-Prozess selbst auf. Nutzen Sie pgrep oder den Trick grep [n]ginx, dessen Muster nicht auf die eigene Befehlszeile passt.

Zustände der Prozesse: R, S, D, Z, T

Der Buchstabe in der Spalte STAT ist kein Beiwerk, sondern der echte Zustand des Prozesses. Davon hängt ab, wie Sie die Last deuten und ob kill überhaupt hilft.

CodeZustandWas es in der Praxis bedeutet
RRunningläuft gerade oder wartet in der Warteschlange auf die CPU
SInterruptible sleepwartet auf ein Ereignis (Netzwerk, Eingabe, Timer); der Normalzustand der meisten Prozesse
DUninterruptible sleepwartet im Kernel auf Ein- und Ausgabe, Signale werden nicht zugestellt
ZZombieist beendet, aber der Elternprozess hat den Exitcode nicht abgeholt
TStoppeddurch das Signal SIGSTOP oder Strg+Z angehalten

Auch die Zusatzzeichen nach dem Buchstaben sind hilfreich: s — Sitzungsleiter, + — Prozess im Vordergrund des Terminals, < — erhöhte Priorität, N — verringerte Priorität, l — mehrere Threads.

Ein Prozess im Zustand D

Ein Prozess im Zustand D befindet sich in einem Systemaufruf und wartet zum Beispiel auf die Antwort einer Festplatte oder eines hängenden NFS-Mounts. Ihm wird kein einziges Signal zugestellt, nicht einmal SIGKILL. Deshalb bringt kill -9 hier nichts. Sie müssen die Ursache des Wartens suchen: iostat, dmesg und den Zustand des Netzwerkspeichers prüfen.

Zombie-Prozesse

Ein Zombie ist bereits tot. Er verbraucht weder CPU noch Speicher, belegt aber nur einen Eintrag in der Prozesstabelle. Abtöten lässt er sich nicht, er ist ja schon beendet. Er verschwindet, sobald der Elternprozess wait() aufruft oder der Elternprozess selbst endet und PID 1 den Zombie übernimmt.

# Zombies und ihre Eltern finden
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /Z/'

Ein einzelner Zombie ist harmlos. Gibt es Hunderte und werden es immer mehr, liegt der Fehler im Elternprogramm. Dieses müssen Sie korrigieren oder neu starten.

top: Prozesse und Last in Echtzeit

top zeigt dieselbe Liste, aktualisiert sie aber alle paar Sekunden und fasst zusätzlich das System zusammen. Das ist der erste Befehl, den man startet, wenn „der Server langsam ist“.

top - 14:21:07 up 12 days,  3:02,  2 users,  load average: 1.84, 1.20, 0.95
Tasks: 213 total,   2 running, 211 sleeping,   0 stopped,   0 zombie
%Cpu(s): 23.1 us,  4.2 sy,  0.0 ni, 70.3 id,  1.9 wa,  0.0 hi,  0.5 si,  0.0 st
MiB Mem :   7821.4 total,    412.6 free,   3105.8 used,   4303.0 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   4398.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1532 www-data  20   0  412308  86420  14212 R  38.2   1.1   1:47.31 php-fpm
   1610 postgres  20   0  221004 154312 148900 S   6.0   1.9   0:31.08 postgres

Am wichtigsten ist die Zeile %Cpu(s): us — Benutzercode, sy — Kernel, id — Leerlauf, wa — Warten auf die Festplatte. Ein hoher Wert bei wa bei freiem Prozessor ist ein sicheres Zeichen dafür, dass der Engpass bei der Ein- und Ausgabe liegt.

Tastenkürzel in top

TasteAktion
P / Msortieren nach CPU / nach Speicher
1jeden Kern einzeln anzeigen
cvollständige Befehlszeile
uFilter nach Benutzer
kSignal an einen Prozess senden
rnice eines Prozesses ändern
HThreads anzeigen
qbeenden

Für Skripte und Logs eignet sich der Stapelmodus: top -b -n 1 | head -20 gibt eine einzige Momentaufnahme ohne Interaktion aus. Einen bestimmten Prozess beobachten Sie mit top -p 1532.

Load Average ist eine Warteschlange, kein Prozentwert

Die drei Zahlen des load average sind die mittlere Länge der Warteschlange über 1, 5 und 15 Minuten. Unter Linux zählen dazu die Prozesse in den Zuständen R und D, der gewöhnliche Schlaf S dagegen nicht. Vergleichen müssen Sie den Wert mit der Anzahl der Kerne (nproc): Bei 4 Kernen bedeutet der Wert 4 volle Auslastung, 12 bedeutet eine Warteschlange, die dreimal so lang ist wie die Kapazität.

Ist der Load hoch, der Prozessor aber untätig, suchen Sie nach Prozessen im Zustand D: ps -eo stat,pid,cmd | grep '^D'. Fast immer ist dann eine langsame Festplatte oder ein Netzwerkspeicher die Ursache.

htop: bequemer Ersatz für top

htop zeigt dasselbe, aber mit farbigen Balken für jeden Kern, Scrollen, Mausbedienung und einer Baumansicht der Prozesse. Meist müssen Sie es erst installieren: sudo apt install htop oder sudo dnf install htop.

  • F3 oder / — Prozess nach Namen suchen;
  • F4 — Filter, der nur die Treffer zeigt;
  • F5 oder t — Baum „Elternprozess — Kindprozesse“;
  • F6 — Spalte zum Sortieren wählen;
  • F7 / F8 — nice verringern oder erhöhen;
  • F9 — Signalmenü für den markierten Prozess;
  • Leertaste — mehrere Prozesse für eine Massenaktion markieren.

Auf Servern, auf denen Sie nichts installieren dürfen, reicht top: Alle wichtigen Aktionen gibt es auch dort.

So beenden Sie einen Prozess: kill und Signale

Der Befehl kill tötet nicht unbedingt, sondern sendet dem Prozess ein Signal. Was dann passiert, hängt vom Signal ab und davon, wie das Programm es verarbeitet.

SignalNummerZweck
SIGHUP1Abbruch des Terminals; viele Dämonen lesen dann ihre Konfiguration neu
SIGINT2Unterbrechung, entspricht Strg+C
SIGKILL9erzwungenes Beenden durch den Kernel, nicht abfangbar
SIGTERM15Bitte, sauber zu beenden; Standard bei kill
SIGSTOP19anhalten, nicht abfangbar
SIGCONT18angehaltenen Prozess fortsetzen
SIGTSTP20Anhalten aus dem Terminal, Strg+Z

Die Nummern gelten für x86 und ARM; die vollständige Liste zeigt kill -l. Signale per Namen anzugeben ist verlässlicher als per Nummer.

kill 1532              # SIGTERM
kill -TERM 1532        # dasselbe, ausdrücklich
kill -HUP $(pidof nginx)   # Konfiguration neu einlesen
kill -STOP 1532; kill -CONT 1532
kill -0 1532 && echo "Prozess läuft"

Das Signal 0 sendet nichts, sondern prüft nur, ob der Prozess existiert und Sie ihm Signale schicken dürfen. In Skripten ist das praktisch.

Warum Sie nicht mit kill -9 anfangen sollten

SIGTERM gibt dem Programm die Chance, Dateien zu schließen, Puffer zu schreiben, Lock-Dateien zu entfernen und Transaktionen sauber abzuschließen. SIGKILL bricht alles sofort ab: Unvollständig geschriebene Daten gehen verloren, temporäre Dateien bleiben liegen, und eine Datenbank muss beim nächsten Start möglicherweise wiederhergestellt werden.

Die richtige Reihenfolge ist:

  1. kill PID senden (SIGTERM).
  2. 5 bis 30 Sekunden warten und mit kill -0 PID prüfen.
  3. Nur wenn der Prozess noch lebt und nicht im Zustand D ist: kill -9 PID.

Für Dienste unter systemd sollten Sie die PID gar nicht von Hand anfassen: systemctl stop sendet selbst SIGTERM, wartet das Timeout ab und beendet den Dienst notfalls mit SIGKILL.

pkill und killall: nach Namen

pkill -f "python worker.py"   # nach der vollständigen Befehlszeile
pkill -u alice                 # alle Prozesse eines Benutzers
killall -TERM node             # alle Prozesse mit dem Namen node
pgrep -l -f worker             # vorher prüfen, was vom Muster erfasst wird

Starten Sie vor einem Massen-pkill immer pgrep mit demselben Muster: -f trifft jeden Teil der Befehlszeile und erfasst dabei leicht auch Unbeteiligtes.

Signale können Sie nur an eigene Prozesse senden. Bei fremden brauchen Sie sudo. Die Meldung Operation not permitted bedeutet genau das.

Priorität der Prozesse: nice und renice

Der nice-Wert sagt dem Scheduler, wer dem Prozessor den Vorrang lassen muss. Der Bereich reicht von -20 (höchste Priorität) bis 19 (lässt allen anderen den Vortritt), Standard ist 0. In top steht er in der Spalte NI, während PR die daraus abgeleitete interne Priorität ist.

# eine schwere Aufgabe mit verringerter Priorität starten
nice -n 10 tar czf backup.tar.gz /var/www

# Priorität eines laufenden Prozesses senken
renice -n 15 -p 1532

# erhöhen (nur root)
sudo renice -n -5 -p 1610

# alle Prozesse eines Benutzers
sudo renice -n 10 -u alice

Normale Benutzer dürfen nur die Priorität eigener Prozesse senken, negative Werte stehen nur root zur Verfügung. Beachten Sie die Grenze von nice: Er wirkt nur auf die CPU. Bremst eine Aufgabe das System über die Festplatte aus, hilft ionice -c3 Befehl. Das ist die Klasse idle, die Festplattenzugriff nur erhält, wenn ihn sonst niemand braucht.

Hintergrundprozesse und Jobs der Shell

Einen Befehl starten Sie im Hintergrund, indem Sie & anhängen, oder Sie halten ihn mit Strg+Z an. Die Shell führt eine Liste der Jobs, die mit eingebauten Befehlen verwaltet werden.

$ long_task &
[1] 5120
$ jobs
[1]+  Running    long_task &
$ fg %1        # in den Vordergrund holen
^Z             # anhalten (SIGTSTP)
$ bg %1        # im Hintergrund fortsetzen

Beim Schließen des Terminals sendet die Shell den Jobs SIGHUP, und sie beenden sich. Damit ein Prozess das überlebt, starten Sie ihn mit nohup Befehl &, lösen ihn mit disown von der Shell oder nutzen tmux. Für dauerhaften Betrieb ist ein systemd-Dienst die richtige Lösung.

Typische Diagnose-Szenarien

Wer frisst den Prozessor?

top -o %CPU            # oder P innerhalb von top
ps -eo pid,user,%cpu,etime,cmd --sort=-%cpu | head

Verbraucht ein Prozess CPU ohne Nutzen, senken Sie zuerst seine Priorität mit renice. Das ist ungefährlich und verschafft Zeit für die Ursachensuche.

Wer belegt einen Port?

sudo ss -ltnp | grep :8080
sudo lsof -i :8080

Die Ausgabe enthält die PID. Mit ihr finden Sie in /proc/PID/ die ausführbare Datei (exe), das Arbeitsverzeichnis (cwd) und die Argumente (cmdline).

Ein Prozess ist unerwartet verschwunden

Eine häufige Ursache ist der OOM Killer, der bei Speichermangel Prozesse beendet. Prüfen Sie das mit dmesg -T | grep -i oom oder journalctl -k | grep -i "killed process".

Fazit

Für die Arbeit mit Prozessen unter Linux reicht ein kleiner Satz Befehle: ps aux für die Momentaufnahme, top und htop zur Beobachtung, kill mit dem richtigen Signal zum Beenden und nice/renice für die Prioritäten. Lesen Sie den Zustand eines Prozesses, bevor Sie handeln: Zombies und Prozesse im Zustand D lassen sich mit Signalen nicht heilen. Beginnen Sie mit SIGTERM und heben Sie kill -9 für den Notfall auf. Prozesse, Speicher, Load Average und Systemaufrufe behandeln wir im Linux-Kurs praxisnah.

Häufige Fragen

Worin unterscheidet sich ps aux von ps -ef?

Das sind zwei Syntaxvarianten desselben Befehls: aux ist der BSD-Stil mit den Spalten %CPU, %MEM und STAT, -ef der System-V-Stil mit der Spalte PPID. Die Liste der Prozesse ist in beiden Fällen dieselbe, nämlich alle Prozesse des Systems.

Wie finde ich heraus, wie viele Prozesse im System laufen?

Am einfachsten sehen Sie in top in die Zeile Tasks oder führen ps -e --no-headers | wc -l aus. Die Anzahl der Threads zeigt ps -eLf --no-headers | wc -l.

Warum endet ein Prozess auch nach kill -9 nicht?

Entweder befindet er sich im Zustand D und wartet im Kernel auf Ein- und Ausgabe, oder es ist ein Zombie, der bereits beendet ist. Im ersten Fall suchen Sie nach einem Problem mit der Festplatte oder dem Netzwerkspeicher, im zweiten korrigieren oder starten Sie den Elternprozess neu.

Was passiert, wenn ich den Prozess mit der PID 1 beende?

Der Kernel schützt init: Normale Signale, auch SIGKILL vom Benutzer, werden ihm nicht zugestellt, solange er sie nicht selbst behandelt. Würde init trotzdem enden, geriete das System in eine Kernel Panic.

Wie begrenze ich den Speicherverbrauch eines Prozesses?

Für einen systemd-Dienst setzen Sie MemoryMax= in der Unit-Datei, für einen einmaligen Start systemd-run --scope -p MemoryMax=500M Befehl. Das arbeitet über cgroups und ist zuverlässiger als das alte ulimit -v.

Das Thema im Video lernen

Dieses Thema wird im Kurs „Linux: с нуля до уверенного администрирования“ ausführlich mit Praxis behandelt.

Zum Kurs