Prozesse in Linux: ps, top, htop, kill, Signale und nice
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.
| Spalte | Bedeutung |
|---|---|
PID | Kennung des Prozesses |
%CPU, %MEM | Anteil am Prozessor und am physischen Speicher |
VSZ | virtueller Speicher in KB (auch das, was nicht im RAM liegt) |
RSS | tatsächlich belegter physischer Speicher in KB |
STAT | Zustand des Prozesses (R, S, D, Z, T) und Zusatzzeichen |
TIME | insgesamt 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.
| Code | Zustand | Was es in der Praxis bedeutet |
|---|---|---|
R | Running | läuft gerade oder wartet in der Warteschlange auf die CPU |
S | Interruptible sleep | wartet auf ein Ereignis (Netzwerk, Eingabe, Timer); der Normalzustand der meisten Prozesse |
D | Uninterruptible sleep | wartet im Kernel auf Ein- und Ausgabe, Signale werden nicht zugestellt |
Z | Zombie | ist beendet, aber der Elternprozess hat den Exitcode nicht abgeholt |
T | Stopped | durch 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
| Taste | Aktion |
|---|---|
P / M | sortieren nach CPU / nach Speicher |
1 | jeden Kern einzeln anzeigen |
c | vollständige Befehlszeile |
u | Filter nach Benutzer |
k | Signal an einen Prozess senden |
r | nice eines Prozesses ändern |
H | Threads anzeigen |
q | beenden |
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.
F3oder/— Prozess nach Namen suchen;F4— Filter, der nur die Treffer zeigt;F5odert— 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.
| Signal | Nummer | Zweck |
|---|---|---|
SIGHUP | 1 | Abbruch des Terminals; viele Dämonen lesen dann ihre Konfiguration neu |
SIGINT | 2 | Unterbrechung, entspricht Strg+C |
SIGKILL | 9 | erzwungenes Beenden durch den Kernel, nicht abfangbar |
SIGTERM | 15 | Bitte, sauber zu beenden; Standard bei kill |
SIGSTOP | 19 | anhalten, nicht abfangbar |
SIGCONT | 18 | angehaltenen Prozess fortsetzen |
SIGTSTP | 20 | Anhalten 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:
kill PIDsenden (SIGTERM).- 5 bis 30 Sekunden warten und mit
kill -0 PIDprüfen. - Nur wenn der Prozess noch lebt und nicht im Zustand
Dist: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.
Dieses Thema wird im Kurs „Linux: с нуля до уверенного администрирования“ ausführlich mit Praxis behandelt.
Zum Kurs