ps (process status) ist das klassische Werkzeug, um zu sehen, was gerade auf einem Linux-System läuft. Anders als top oder htop liefert ps keinen Live-Stream, sondern einen Snapshot zum Zeitpunkt des Aufrufs — eine Zeile pro Prozess, einmal eingefroren. Das macht ps ideal für Skripte, Pipes, schnelle Übersichten und gezielte Filter.

Was ps macht

ps fragt den Kernel über /proc ab und gibt eine Liste aller (oder gefilterter) Prozesse aus — mit PID, Eigentümer, CPU-/Speicher-Nutzung, Status und Befehlszeile. Die Ausgabe ist statisch: Was du siehst, ist der Stand zum Zeitpunkt des Aufrufs. Wer fortlaufende Updates will, nutzt top, htop oder kombiniert ps mit watch.

ps selbst ist Teil des procps-Pakets (heute meistens procps-ng) und auf praktisch jedem Linux-System vorhanden. Auf BSD und macOS gibt es eine eigene Variante mit teils abweichender Semantik — was bei ps zu den berüchtigten Optionen-Mehrdeutigkeiten führt.

Bash Schneller Snapshot aller eigenen Prozesse
ps
Output
  PID TTY          TIME CMD
 3421 pts/0    00:00:00 bash
 4187 pts/0    00:00:00 ps

Ohne Optionen zeigt ps nur die Prozesse der aktuellen Shell-Session — meistens wenig spannend. Erst die Optionen machen ps nützlich.

Drei Optionen-Stile

ps ist historisch gewachsen und vereint drei Welten in einem Befehl. Welche Schreibweise du nutzt, ist Geschmack — wichtig ist, dass du die Unterschiede kennst, weil sie sich teils sehr unterschiedlich verhalten.

StilSchreibweiseBeispielHerkunft
UNIXmit Bindestrichps -efPOSIX / SysV
BSDohne Bindestrichps auxBSD-Tradition
GNU longdoppelter Bindestrichps --forestGNU-Erweiterungen

Mischen ist erlaubt, kann aber verwirrend werden — ps -aux ist nicht dasselbe wie ps aux, dazu mehr in den Stolperfallen. Im Alltag haben sich zwei Varianten als „Standard” etabliert: ps aux (BSD) und ps -ef (UNIX). Welche du nimmst, ist meistens reine Gewohnheit.

Standard-Patterns: aux und -ef

Beide Aufrufe zeigen alle Prozesse aller Benutzer — der Unterschied liegt in den Default-Spalten und in einigen Details.

Bash BSD-Stil: alle Prozesse aller User
ps aux
Output
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 168432 11892 ?        Ss   May03   0:04 /sbin/init
root         412  0.0  0.0  47120  5984 ?        Ss   May03   0:01 /lib/systemd/systemd-journald
michael     3421  0.0  0.0  21344  5120 pts/0    Ss   09:11   0:00 -bash
michael     4187  0.0  0.0  19112  3712 pts/0    R+   09:42   0:00 ps aux

Eine Zeile pro Prozess: Eigentümer, PID, aktuelle CPU- und Speicher-Auslastung in Prozent, virtueller und residenter Speicher in Kilobytes, das kontrollierende Terminal, der Status-Code, Startzeit, kumulierte CPU-Zeit und der vollständige Aufruf.

Bash UNIX-Stil mit Eltern-PID
ps -ef
Output
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 May03 ?        00:00:04 /sbin/init
root         412       1  0 May03 ?        00:00:01 /lib/systemd/systemd-journald
michael     3421    3418  0 09:11 pts/0    00:00:00 -bash
michael     4188    3421  0 09:42 pts/0    00:00:00 ps -ef

-ef zeigt zusätzlich die PPID (Parent-PID) und macht damit die Eltern-Kind-Beziehungen sichtbar. Dafür fehlen %CPU, %MEM, VSZ und RSS — die sind eher der Stärken-Bereich von aux. Wer Hierarchie sehen will, nimmt -ef (oder direkt --forest); wer Ressourcen-Verbrauch sehen will, nimmt aux.

Spalten interpretieren

Die wichtigsten Spalten und was sie bedeuten:

SpalteBedeutung
UID / USEREigentümer des Prozesses
PIDProcess ID, eindeutige Nummer pro laufendem Prozess
PPIDParent Process ID, der Prozess, der diesen gestartet hat
%CPUAnteil CPU-Zeit seit Prozessstart, gemittelt
%MEMAnteil RSS am gesamten physischen RAM
VSZVirtual Size in KiB, der gesamte adressierbare Speicher
RSSResident Set Size in KiB, tatsächlich im RAM gehaltener Anteil
TTYkontrollierendes Terminal, ? bei Daemons ohne TTY
STATProzess-Status mit Modifiern, siehe nächste Sektion
START / STIMEStartzeitpunkt des Prozesses
TIMEbisher verbrauchte CPU-Zeit (kumuliert)
CMD / COMMANDaufgerufener Befehl mit Argumenten

VSZ und RSS werden gerne verwechselt: VSZ ist der gesamte virtuelle Adressraum eines Prozesses — inklusive gemappter Bibliotheken, ungenutzter Allokationen und shared Memory. RSS ist der Anteil davon, der gerade tatsächlich im physischen RAM liegt. Für „wie viel RAM verbraucht der Prozess?” ist RSS die ehrlichere Antwort, wobei auch das durch shared Pages noch über die Realität liegen kann.

STAT-Codes

Die STAT-Spalte besteht aus einem Hauptstatus und optionalen Modifiern. Den Hauptteil kennst du aus dem Prozess-Modell, die Modifier kommen hinzu.

CodeBedeutungTyp
Rrunning oder runnable (auf der CPU oder in der Run-Queue)Hauptstatus
Sinterruptible sleep (wartet auf Ereignis, weckbar)Hauptstatus
Duninterruptible sleep (meistens auf I/O)Hauptstatus
Tgestoppt (SIGSTOP, SIGTSTP oder Tracer)Hauptstatus
Zzombie (beendet, aber Eltern hat noch nicht wait() aufgerufen)Hauptstatus
<erhöhte Priorität (negativer Nice-Wert)Modifier
Nreduzierte Priorität (positiver Nice-Wert)Modifier
+im Vordergrund einer ProzessgruppeModifier
sSession LeaderModifier
lmulti-threaded (verwendet Kernel-Threads)Modifier
Lhat Pages im Speicher gelocktModifier

Ss ist also „interruptible sleeping session leader” — typisch für Daemons. R+ ist „läuft im Vordergrund” — typisch für ein gerade gestartetes Kommando. Z ohne weiteres ist immer ein Hinweis auf einen Zombie, den jemand einsammeln müsste.

Custom-Output mit -o

Mit -o legst du selbst fest, welche Spalten erscheinen. Das ist die Königsdisziplin von ps: Du bekommst genau die Daten, die du brauchst, in der Reihenfolge, die du willst — perfekt für Pipes und Skripte.

Bash Eigene Spalten, sortiert nach CPU-Auslastung
ps -eo pid,user,stat,start,cmd --sort=-%cpu
Output
  PID USER     STAT  STARTED CMD
 2912 michael  Sl     May03 /usr/lib/firefox/firefox
 3187 michael  Sl     May03 /usr/bin/code --no-sandbox
    1 root     Ss     May03 /sbin/init
 4192 michael  R+     09:43 ps -eo pid,user,stat,start,cmd --sort=-%cpu

-e heißt „alle Prozesse” (wie das a in aux), -o legt das Format fest, --sort=-%cpu sortiert absteigend (das Minus-Zeichen kehrt um). Eine vollständige Liste aller verfügbaren Format-Specifier liefert ps L:

Bash Alle Format-Specifier auflisten
ps L

Häufig genutzte Specifier sind pid, ppid, pgid, sid, user, uid, pcpu, pmem, rss, vsz, stat, start, time, etime (Laufzeit seit Start), comm (nur Prozessname) und cmd (komplette Kommandozeile).

Filter und Sortieren

Statt erst alles auszugeben und dann mit grep zu filtern, kann ps direkt einschränken — sauberer und in Skripten robuster.

Bash Nur Prozesse eines Users
ps -u michael
Bash Konkrete PIDs anzeigen
ps -p 1,412,3421
Bash Nach Befehlsname filtern
ps -C bash

-C matcht den Prozessnamen (also den comm-Wert, nicht die volle Kommandozeile), mehrere Namen kommagetrennt. Für Sortierung nutzt du --sort= mit einem Specifier — Minus-Zeichen kehrt die Richtung um:

Bash Nach Speicher absteigend
ps aux --sort=-rss
Bash Nach Startzeit aufsteigend
ps -eo pid,etime,cmd --sort=etime

Alternativ funktioniert auch klassisch via Pipe (ps aux | sort -k 4 -nr), das ist aber fehleranfälliger als --sort direkt in ps.

Praxis-Patterns

Diese Aufrufe braucht man im Alltag immer wieder — als Aliases oder im Muskelgedächtnis nützlich.

Bash Top-CPU-Verbraucher
ps aux --sort=-%cpu | head

Sortiert alle Prozesse absteigend nach CPU-Anteil und schneidet die Top 10 ab. Schnellste Antwort auf „Wer frisst gerade meine CPU?” — wobei der Wert über die Lebenszeit des Prozesses gemittelt ist, also kurze Spitzen zeigt top besser.

Bash Top-Memory-Verbraucher
ps aux --sort=-%mem | head

Dasselbe für Speicher. Browser, Java-Prozesse und Datenbanken landen hier fast immer in der Spitzengruppe. Für genauere Aussagen über tatsächlich „verbrauchten” RAM lohnt zusätzlich ein Blick auf smem oder /proc/PID/status.

Bash Prozess-Hierarchie als Baum
ps -ef --forest

--forest zeichnet die Eltern-Kind-Struktur als ASCII-Baum direkt in die CMD-Spalte. Praktisch, um Daemon-Trees (systemd -> Service -> Worker) oder Shell-Hierarchien (Terminal -> Shell -> gestartete Programme) zu verstehen.

Bash Eigene Prozesse
ps -u $USER

Filtert auf den aktuellen Login-User. Auf Mehrbenutzer-Systemen oder Servern oft das Erste, was man sehen will, bevor man nach root-Prozessen sucht.

Bash PID via Name finden — pgrep als Vergleich
pgrep -a sshd

pgrep ist der spezialisierte Bruder von ps: Er sucht Prozesse nach Name oder Muster und gibt nur PIDs (oder mit -a zusätzlich die Kommandozeile) aus. Für Skripte ist pgrep fast immer eleganter als ps ... | grep ... | awk ....

Stolperfallen

aux und -aux sind nicht dasselbe

Klassische Verwechslung: ps aux ist BSD-Stil und zeigt alle Prozesse aller User mit Detailspalten. ps -aux ist UNIX-Stil und sollte streng genommen „alle Prozesse von User x” bedeuten — moderne procps-Versionen geben dafür eine Warnung aus und behandeln den Aufruf wie aux, aber verlassen darf man sich darauf nicht. Merksatz: Im BSD-Stil keine Bindestriche.

ps zeigt nur einen Snapshot

ps friert den Zustand zum Zeitpunkt des Aufrufs ein. Kurze Spitzen, kurzlebige Prozesse oder ein sich ändernder STAT bleiben unsichtbar. Für Live-Beobachtung ist top/htop die richtige Wahl, oder watch -n 1 ‘ps aux —sort=-%cpu | head’, um den Snapshot regelmäßig neu zu zeichnen.

Threads vs. Prozesse

Standardmäßig zeigt ps nur Prozesse, keine einzelnen Threads. Mehrgewichtige Programme (Browser, JVM, Datenbanken) erscheinen als ein Eintrag, obwohl intern Dutzende Threads laufen. Mit -T oder -L bekommst du eine Zeile pro Thread inklusive SPID/LWP. Sichtbar wird das auch im STAT-Modifier l (lower-case L) für „multi-threaded”.

CMD wird in Default-Breite abgeschnitten

Lange Kommandozeilen schneidet ps auf die Terminal-Breite zu — was beim Debuggen genau die Information versteckt, die du brauchst. Mit -w bekommst du eine breitere Ausgabe, mit -ww wird die Kommandozeile gar nicht mehr abgeschnitten. In Pipes (also wenn das Ausgabe-Ziel kein Terminal ist) erkennt ps das oft selbst, aber sicher ist -ww.

START-Format wechselt für ältere Prozesse

Solange ein Prozess am gleichen Tag gestartet wurde, zeigt ps die Uhrzeit (09:42). Älter als 24 Stunden, kommt das Datum (May03); noch älter, das Jahr. Für reproduzierbare Ausgaben in Skripten lieber explizit -o lstart oder etime nutzen — die liefern ein stabiles Format.

VSZ ist nicht der reale Speicherverbrauch

Ein Prozess kann ein VSZ von 2 GiB haben und trotzdem nur 50 MiB physischen RAM (RSS) belegen — der Rest sind ungenutzte virtuelle Adressen, gemappte Libraries oder Shared Memory. Wer „wie viel RAM frisst Prozess X?” beantworten will, schaut auf RSS, idealerweise mit Tools wie smem, die zusätzlich Shared Pages berücksichtigen.

Zombies erkennt man an STAT=Z

Ein Prozess im Status Z ist beendet, sein Exit-Status wartet aber noch im Kernel auf wait() durch den Eltern-Prozess. Zombies belegen kaum Ressourcen (nur einen Eintrag in der Prozess-Tabelle), aber viele davon weisen auf einen Bug im Eltern-Prozess hin. Killen lassen sie sich nicht direkt — der Eltern-Prozess muss reagieren oder selbst beendet werden, dann erbt init die Zombies und räumt auf.

ps selbst taucht in der Liste auf

Wer ps aux | grep firefox schreibt, sieht in der Ausgabe oft auch die grep-Zeile selbst, weil grep firefox ja den String „firefox” enthält. Klassischer Trick: ps aux | grep [f]irefox — die Zeichenklasse matcht zwar das gleiche, aber im ps-Output steht [f]irefox wörtlich, nicht firefox, und fällt durchs Filter. Sauberer ist von Anfang an pgrep -a firefox.

Weiterführende Ressourcen

Externe Quellen

  • Prozess-Modell — PID, PPID, Status-Codes und Lebenszyklus
  • top — Live-Monitor als Live-Pendant zu ps
  • htop — Interaktiver Prozess-Browser mit Tree-Ansicht
  • kill — Prozesse beenden, sobald die PID via ps gefunden ist
  • Signale — Was hinter SIGSTOP, SIGTERM und Co. steckt
/ Weiter

Zurück zu Prozesse & Jobs

Zur Übersicht