Zum Inhalt springen

Prozesse

Ein Programm hängt, die VM wird plötzlich langsam, ein Dienst läuft doppelt. In allen drei Fällen brauchst du dieselben Werkzeuge: Prozesse anzeigen, verstehen, beenden. Das ist tägliche Arbeit auf jedem Server, und es geht ohne Task-Manager.

Ein Programm ist eine Datei auf der Platte, etwa /usr/bin/sleep. Ein Prozess ist dieses Programm, während es läuft: mit eigenem Speicher, einem Besitzer, geöffneten Dateien und einer Nummer, der PID (process ID). Der Kernel führt die Prozesstabelle und teilt die CPU zu.

Jeder Prozess wird von einem anderen gestartet, dem Elternprozess, dessen PID als PPID vermerkt ist. So entsteht ein Baum. Ganz oben steht PID 1: Auf Ubuntu ist das systemd, das beim Booten als erstes Programm startet und alle Dienste hochfährt. In älteren Unterlagen heisst PID 1 noch init; der Name lebt als Symlink weiter.

Terminal-Fenster
ps -p 1 -o pid,ppid,user,comm
ls -l /sbin/init
echo "$$"

$$ ist die PID deiner aktuellen Shell. Jeder Befehl, den du eintippst, wird ein Kindprozess davon.

ps zeigt eine Momentaufnahme. Es hat zwei Optionsstile (BSD ohne Strich, Unix mit Strich), beide sind verbreitet:

Terminal-Fenster
ps aux | head -n 5
ps -ef | head -n 5
ps -u "$USER"
ps -o pid,ppid,stat,cmd --forest -u "$USER"

Die wichtigsten Spalten von ps aux:

Spalte Bedeutung
USER Unter welchem Konto der Prozess läuft
PID Prozessnummer
%CPU, %MEM Anteil an Prozessor und Arbeitsspeicher
STAT Zustand: R läuft, S schläft (wartet), T gestoppt, Z Zombie (beendet, aber vom Elternprozess noch nicht abgeholt)
START, TIME Startzeit und verbrauchte CPU-Zeit
COMMAND Der Befehl mit Argumenten. In eckigen Klammern: Kernel-Threads

Den Baum zeigt pstree. Falls es fehlt: sudo apt install psmisc.

Terminal-Fenster
pstree -p | head -n 20
pstree -p "$$"

Hands-on: Wo steckt dein Terminal? Verfolge die Kette von deiner Shell bis zu PID 1.

Terminal-Fenster
pstree -sp "$$"

top aktualisiert sich alle drei Sekunden. Der Kopfbereich zeigt Laufzeit, Load Average, CPU- und Speichersummen, darunter die Prozessliste, sortiert nach CPU.

Terminal-Fenster
top

Tasten in top:

Taste Wirkung
h Hilfe
P / M Nach CPU / nach Speicher sortieren
u Nur Prozesse eines Benutzers
1 Jede CPU einzeln anzeigen
k Prozess beenden (fragt nach PID und Signal)
q Beenden

htop kann dasselbe, ist aber farbig, mit Maus bedienbar und zeigt die Funktionstasten unten an. Auf Servern ist es oft das Erste, was man nachinstalliert:

Terminal-Fenster
sudo apt install htop
htop

Prozesse beendet man nicht, man schickt ihnen ein Signal. Was der Prozess damit macht, entscheidet er meist selbst.

Signal Nummer Bedeutung
SIGTERM 15 Bitte beenden. Der Prozess kann aufräumen. Standard von kill
SIGKILL 9 Sofort weg. Der Kernel beendet den Prozess, keine Chance aufzuräumen
SIGHUP 1 Terminal weg. Viele Dienste lesen darauf ihre Konfiguration neu
SIGINT 2 Was Ctrl+C schickt
SIGSTOP / SIGCONT 19 / 18 Anhalten und fortsetzen
Terminal-Fenster
kill -l
kill 12345
kill -TERM 12345
kill -9 12345

Die Reihenfolge ist immer dieselbe: zuerst kill PID, ein paar Sekunden warten, erst dann kill -9. Ein Prozess, der mit SIGKILL stirbt, kann keine Dateien schliessen und keine Lock-Dateien aufräumen. Eine Datenbank dankt es dir nicht.

Wer die PID nicht kennt, sucht nach dem Namen:

Terminal-Fenster
pgrep -a sleep
pkill sleep
killall sleep
pkill -f "sleep 300"

pgrep zeigt nur, pkill schickt das Signal. -f sucht in der ganzen Befehlszeile statt nur im Programmnamen. Fremde Prozesse darfst du nicht beenden, dafür braucht es sudo.

Ein Befehl blockiert die Shell, bis er fertig ist. Mit & am Ende startet er im Hintergrund, und du bekommst den Prompt sofort zurück.

Hands-on: Spiel das einmal durch.

  1. Prozess im Hintergrund starten. Die Shell zeigt Jobnummer und PID:
    Terminal-Fenster
    sleep 300 &
    jobs
  2. Einen zweiten im Vordergrund starten, mit Ctrl+Z anhalten, dann im Hintergrund weiterlaufen lassen:
    Terminal-Fenster
    sleep 200
    # Ctrl+Z
    jobs
    bg %2
    jobs
  3. Einen Job in den Vordergrund holen und mit Ctrl+C beenden:
    Terminal-Fenster
    fg %2
    # Ctrl+C
  4. Den ersten gezielt beenden, über die Jobnummer oder die PID:
    Terminal-Fenster
    kill %1
    jobs

Hintergrundjobs gehören zu deiner Shell. Schliesst du das Terminal, bekommen sie SIGHUP und sterben mit. Soll etwas weiterlaufen, startest du es mit nohup und leitest die Ausgabe um:

Terminal-Fenster
nohup ./langer-job.sh > job.log 2>&1 &

Für echte Dienste ist das keine Lösung, dafür gibt es systemd (Modul 9). Für einen einmaligen langen Lauf über SSH reicht nohup, oder tmux.

Der Scheduler verteilt die CPU fair. Mit nice sagst du, dass ein Prozess anderen den Vortritt lassen soll. Die Skala geht von -20 (wichtig) bis 19 (nett zu allen anderen), Standard ist 0. Nur root darf unter 0.

Terminal-Fenster
nice -n 15 tar czf backup.tgz /home &
renice -n 5 -p 12345
Terminal-Fenster
uptime
nproc
14:02:11 up 3 days, 2:14, 2 users, load average: 0.52, 0.31, 0.18

Der Load Average ist die durchschnittliche Zahl von Prozessen, die laufen oder auf CPU oder Platte warten, über 1, 5 und 15 Minuten. Die Zahl ist nur im Verhältnis zur Anzahl CPUs sinnvoll: Load 2 auf einer CPU heisst Dauerstau, auf vier CPUs ist es halbe Auslastung. Steigt die 1-Minuten-Zahl über die 15-Minuten-Zahl, wird es gerade schlimmer.

Das Verzeichnis /proc ist kein Verzeichnis auf der Platte, sondern eine Sicht auf den Kernel, als Dateien verkleidet. ps und top lesen genau hier.

Terminal-Fenster
ls /proc | head
cat /proc/loadavg
grep -E 'model name|^cpu cores' /proc/cpuinfo | sort -u
grep -E 'MemTotal|MemAvailable' /proc/meminfo
free -h

Für jeden Prozess gibt es ein Unterverzeichnis mit seiner PID:

Terminal-Fenster
ls /proc/$$
head -n 10 /proc/$$/status
tr '\0' ' ' < /proc/$$/cmdline; echo

Bei free -h zählt die Spalte available, nicht free. Linux nutzt freien Speicher als Dateicache und gibt ihn bei Bedarf sofort wieder her. Wenig free ist normal, wenig available ist ein Problem.

Lösung anzeigen
Terminal-Fenster
script labs/linux/06-system/prozesse.txt
ps -p 1 -o pid,user,comm
# PID 1 ist systemd, läuft als root.
sleep 300 &
sleep 400 &
jobs
pgrep -a sleep
pstree -p "$$"
# Elternprozess beider sleep ist meine Bash (PID aus echo $$).
kill %1
kill "$(pgrep -f 'sleep 400')"
jobs
# kill ohne Option schickt SIGTERM (15).
sleep 500
# Ctrl+Z
jobs
# Zustand: Stopped
bg %1
pkill -f 'sleep 500'
jobs
uptime
nproc
# Load 0.15 bei 2 CPUs: fast nichts zu tun.
free -h
# 4 GiB total, 3.1 GiB available. free ist kleiner, weil der Kernel
# den Rest als Dateicache nutzt, der bei Bedarf sofort frei wird.
exit

Selbstcheck · 5 Fragen

1. Welcher Prozess hat auf Ubuntu 24.04 die PID 1?
2. Was schickt kill 1234 ohne weitere Option?
3. Wann ist kill -9 angebracht?
4. Was bedeutet load average 4.0 auf einer VM mit 2 CPUs?
5. Welche Aussagen zu Hintergrundjobs stimmen? (mehrere Antworten möglich)