Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Prozesse & Signale

Dieses Kapitel behandelt erweiterte Tools zur Prozessüberwachung, das Signal-System zur Prozesskommunikation und die Verwaltung von Prozessgruppen und Jobs.

1 Erweiterte Monitoring-Tools

Neben den Standard-Tools ps, top und htop bietet macOS spezialisierte Werkzeuge für detailliertes System-Monitoring.

1.1 iotop – I/O-Überwachung

macOS hat kein natives iotop wie Linux, aber es gibt Alternativen:

Alternative 1: sudo iotop (falls installiert)

# Installation (falls verfügbar)
brew install iotop

# Ausführen (benötigt root)
sudo iotop

Alternative 2: fs_usage für I/O-Überwachung

# Disk-I/O aller Prozesse
sudo fs_usage -f diskio

# Bestimmter Prozess
sudo fs_usage -f diskio -w | grep Safari

Alternative 3: iostat – Disk-Statistiken

# Disk-I/O Statistiken
iostat

# Alle 2 Sekunden aktualisieren
iostat -w 2

# Detailliert mit Disk-Namen
iostat -d

# Bestimmtes Intervall, 5 Messungen
iostat 2 5

Ausgabe verstehen:

          disk0       cpu    load average
    KB/t  tps  MB/s  us sy id   1m   5m   15m
   24.00   45  1.06   5  3 92  1.23 1.45 1.67
SpalteBeschreibung
KB/tKilobytes pro Transfer
tpsTransfers pro Sekunde
MB/sMegabytes pro Sekunde
us/sy/idCPU: User/System/Idle %

Alternative 4: Activity Monitor CLI-Daten

# Top-Prozesse nach Disk-Nutzung
top -o disk -l 1 -n 10 | tail -n +13

1.2 vm_stat – Speicherstatistiken

vm_stat zeigt detaillierte Statistiken des virtuellen Speichersystems.

Grundlegende Nutzung:

# Einmalige Ausgabe
vm_stat

# Ausgabe:
# Mach Virtual Memory Statistics: (page size of 16384 bytes)
# Pages free:                               12345.
# Pages active:                             67890.
# Pages inactive:                           11111.
# Pages speculative:                         2222.
# Pages throttled:                              0.
# Pages wired down:                         33333.
# Pages purgeable:                           4444.
# ...

Kontinuierliche Überwachung:

# Alle 1 Sekunde
vm_stat 1

# Alle 5 Sekunden
vm_stat 5

Ausgabe verstehen:

MetrikBeschreibung
Pages freeFreie Speicherseiten
Pages activeAktiv genutzter Speicher
Pages inactiveKürzlich ungenutzt, noch im RAM
Pages speculativeSpekulativ geladene Daten
Pages wired downVom Kernel gesperrt (nicht auslagerbar)
Pages purgeableKann bei Bedarf freigegeben werden
PageinsVon Disk in RAM geladen
PageoutsVon RAM auf Disk ausgelagert
Swapins/SwapoutsSwap-Aktivität

In lesbare Werte umrechnen:

# Page-Größe ermitteln
pagesize=$(vm_stat | head -1 | grep -oE '[0-9]+')

# Freier Speicher in MB
free_pages=$(vm_stat | grep "Pages free" | awk '{print $3}' | tr -d '.')
echo "Frei: $(( free_pages * pagesize / 1024 / 1024 )) MB"

Skript für lesbare Ausgabe:

#!/bin/zsh
# mem-usage.sh

pagesize=$(pagesize)

get_pages() {
    vm_stat | grep "$1" | awk '{print $NF}' | tr -d '.'
}

free=$(($(get_pages "Pages free") * pagesize / 1024 / 1024))
active=$(($(get_pages "Pages active") * pagesize / 1024 / 1024))
inactive=$(($(get_pages "Pages inactive") * pagesize / 1024 / 1024))
wired=$(($(get_pages "Pages wired") * pagesize / 1024 / 1024))

echo "Speicher-Nutzung:"
echo "  Frei:     ${free} MB"
echo "  Aktiv:    ${active} MB"
echo "  Inaktiv:  ${inactive} MB"
echo "  Wired:    ${wired} MB"

1.3 fs_usage – Dateisystem-Aktivität

fs_usage zeigt Dateisystem-Aktivität in Echtzeit – ideal zum Debuggen von I/O-Problemen.

Grundlegende Nutzung:

# Alle Dateisystem-Aktivität (benötigt root)
sudo fs_usage

# Nur Disk-I/O
sudo fs_usage -f diskio

# Nur Netzwerk
sudo fs_usage -f network

# Nur Dateisystem-Calls
sudo fs_usage -f filesys

Nach Prozess filtern:

# Bestimmter Prozess (Name)
sudo fs_usage -w Safari

# Bestimmte PID
sudo fs_usage -w -p 1234

# Mehrere Prozesse
sudo fs_usage -w Safari Chrome Firefox

# Prozess ausschließen
sudo fs_usage -e Safari

Ausgabe-Optionen:

# Breite Ausgabe (vollständige Pfade)
sudo fs_usage -w

# Mit Timestamps
sudo fs_usage -t

# Kombiniert
sudo fs_usage -w -f diskio -t

Ausgabe verstehen:

14:23:45  RdData     D=0x012345  B=0x1000  /path/to/file   Safari
14:23:45  open       F=3         /path/to/file             Safari
14:23:45  read       F=3  B=0x400                          Safari
14:23:45  close      F=3                                   Safari
SpalteBeschreibung
TimestampZeitstempel
Operationread, write, open, close, stat, etc.
F=File Descriptor
B=Bytes
D=Disk Block
PfadBetroffene Datei
ProzessProzessname

Praktische Anwendungen:

# Was liest/schreibt ein Prozess?
sudo fs_usage -w -f diskio Spotlight

# Welche Dateien öffnet eine App beim Start?
sudo fs_usage -w -f filesys Safari 2>&1 | grep open

# Netzwerkaktivität eines Prozesses
sudo fs_usage -w -f network curl

# In Datei protokollieren
sudo fs_usage -w Safari > fs_log.txt 2>&1 &
# Später: kill %1

1.4 nettop – Netzwerk pro Prozess

nettop zeigt Netzwerkverbindungen und Bandbreite pro Prozess – wie top für Netzwerk.

Grundlegende Nutzung:

# Interaktive Ansicht
nettop

# Nicht-interaktiv (einmalig)
nettop -l 1

# Alle 2 Sekunden, 5 Messungen
nettop -l 5 -s 2

Filter-Optionen:

# Nur TCP
nettop -t tcp

# Nur UDP
nettop -t udp

# Bestimmter Prozess
nettop -p Safari

# Nur mit Traffic (Delta-Modus)
nettop -d

Ausgabe-Optionen:

# Nur bestimmte Spalten
nettop -c all       # Alle Spalten
nettop -c bytes_in,bytes_out

# Sortieren
nettop -o bytes_in  # Nach eingehenden Bytes

# JSON-Ausgabe
nettop -j -l 1

Interaktive Tastenkürzel:

TasteFunktion
qBeenden
dDelta-Modus (nur Änderungen)
eProzesse ein-/ausklappen
hHilfe
pNach Prozess sortieren
bNach Bytes sortieren

Ausgabe verstehen:

                        bytes_in  bytes_out  rx_dupe  ...
Safari.1234               1.2MB     45.6KB       0
  tcp4  192.168.1.100:52341  ->  93.184.216.34:443   512KB   12KB
Chrome.5678               800KB    123.4KB       0

Praktische Beispiele:

# Top-Netzwerknutzer
nettop -l 1 -t wifi | head -20

# Verbindungen eines Prozesses
nettop -p Safari -l 1

# Bandbreite überwachen
watch -n 1 "nettop -l 1 -d | head -15"

Alternativen:

# lsof für Netzwerkverbindungen
lsof -i -n -P

# netstat
netstat -an -p tcp

# Aktivitätsmonitor CLI (Netzwerk-Tab)
nettop -c state,bytes_in,bytes_out -l 1

2 Signale

Signale sind der primäre Mechanismus zur Kommunikation mit Prozessen unter Unix. Sie können Prozesse beenden, pausieren, fortsetzen oder benutzerdefinierte Aktionen auslösen.

2.1 Signal-Übersicht (SIGTERM, SIGKILL, SIGHUP, …)

Wichtige Signale:

SignalNummerBeschreibungAbfangbar
SIGHUP1Hangup (Terminal geschlossen)Ja
SIGINT2Interrupt (Ctrl+C)Ja
SIGQUIT3Quit mit Core-Dump (Ctrl+)Ja
SIGKILL9Sofort beenden (nicht abfangbar!)Nein
SIGTERM15Sauber beenden (Standard)Ja
SIGSTOP17Prozess anhaltenNein
SIGTSTP18Terminal Stop (Ctrl+Z)Ja
SIGCONT19FortsetzenJa
SIGUSR130Benutzerdefiniert 1Ja
SIGUSR231Benutzerdefiniert 2Ja
SIGCHLD20Kind-Prozess beendetJa
SIGALRM14Timer abgelaufenJa
SIGPIPE13Schreiben in geschlossene PipeJa

Alle Signale anzeigen:

kill -l
# HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM ...

Signal-Verhalten:

SignalTypische Reaktion
SIGTERMSauberes Herunterfahren, Aufräumen
SIGKILLSofortiger Tod, keine Aufräumarbeiten
SIGHUPKonfiguration neu laden (Daemons)
SIGINTInteraktiver Abbruch
SIGSTOP/CONTPausieren/Fortsetzen

Best Practice:

1. Erst SIGTERM (15) versuchen – gibt Prozess Zeit zum Aufräumen
2. Warten (einige Sekunden)
3. Falls nötig: SIGKILL (9) – als letzter Ausweg

2.2 kill – Signale an Prozesse senden

Trotz des Namens kann kill alle Signale senden, nicht nur beenden.

Syntax:

kill [-SIGNAL] PID...

Grundlegende Nutzung:

# Standard: SIGTERM (15)
kill 1234

# SIGKILL (sofort beenden)
kill -9 1234
kill -KILL 1234

# SIGHUP (Konfiguration neu laden)
kill -1 1234
kill -HUP 1234

# SIGSTOP (pausieren)
kill -STOP 1234

# SIGCONT (fortsetzen)
kill -CONT 1234

Mehrere Prozesse:

# Mehrere PIDs
kill 1234 5678 9012

# Alle Prozesse einer Gruppe
kill -TERM -1234    # Negative PID = Prozessgruppe

# Mit $! (letzter Hintergrundprozess)
sleep 100 &
kill $!

Existenz prüfen:

# Signal 0 prüft nur, ob Prozess existiert
kill -0 1234 && echo "Prozess existiert" || echo "Nicht gefunden"

2.3 kill -s – Signal nach Name

Signale können auch mit -s und Namen angegeben werden.

Syntax:

kill -s SIGNALNAME PID

Beispiele:

# Nach Name
kill -s TERM 1234
kill -s KILL 1234
kill -s HUP 1234

# Äquivalent zu
kill -TERM 1234
kill -15 1234

Alle verfügbaren Signalnamen:

kill -l
# 1) SIGHUP     2) SIGINT     3) SIGQUIT    4) SIGILL
# 5) SIGTRAP    6) SIGABRT    7) SIGEMT     8) SIGFPE
# 9) SIGKILL   10) SIGBUS    11) SIGSEGV   12) SIGSYS
# ...

2.4 pkill – Prozesse nach Name beenden

pkill sendet Signale an Prozesse basierend auf Namen oder anderen Kriterien.

Syntax:

pkill [Optionen] MUSTER

Grundlegende Nutzung:

# Nach Prozessname (Teilmatch)
pkill Safari
pkill -9 Safari      # SIGKILL

# Exakter Name
pkill -x Safari

# Case-insensitive
pkill -i safari

Erweiterte Filter:

# Nach Benutzer
pkill -u max Safari

# Nach Gruppe
pkill -g staff Firefox

# Nach Terminal
pkill -t ttys001

# Ältere als X Sekunden
pkill -o -older 3600 process

# Jüngste Instanz
pkill -n process

# Eltern-PID
pkill -P 1234

Optionen:

OptionBeschreibung
-SIGNALSignal angeben (-9, -HUP, etc.)
-u USERNach Benutzer
-g GROUPNach Gruppe
-t TTYNach Terminal
-P PPIDNach Eltern-PID
-xExakter Name
-iCase-insensitive
-nNur neuester Prozess
-oNur ältester Prozess
-fVollständige Kommandozeile matchen

Trockenlauf mit pgrep:

# Erst prüfen was gematcht wird
pgrep -l Safari
# 1234 Safari

# Dann killen
pkill Safari

2.5 killall – Alle Prozesse eines Namens

killall beendet alle Prozesse mit exakt dem angegebenen Namen.

Syntax:

killall [Optionen] PROZESSNAME

Grundlegende Nutzung:

# Alle Safari-Prozesse beenden
killall Safari

# Mit SIGKILL
killall -9 Safari
killall -KILL Safari

# Mit SIGHUP
killall -HUP nginx

Optionen:

# Interaktiv (Bestätigung)
killall -i Safari

# Verbose
killall -v Safari

# Nach Benutzer
killall -u max Safari

# Ältere als X Sekunden
killall -o 1h Safari    # älter als 1 Stunde
killall -y 5m Safari    # jünger als 5 Minuten

# Regex
killall -r "^Safari"

Optionen-Übersicht:

OptionBeschreibung
-SIGNALSignal angeben
-vVerbose
-iInteraktiv (fragen)
-u USERNach Benutzer
-o TIMEÄlter als
-y TIMEJünger als
-rRegex-Match
-zAuch Zombies

Unterschied pkill vs killall:

Merkmalpkillkillall
MatchingTeilstring/RegexExakter Name (Standard)
KommandozeileMit -fNein
FilterUmfangreichBasis
PortabilitätPOSIX-ähnlichBSD/macOS

Praktische Beispiele:

# Alle Python-Prozesse
killall python3

# Alle Hintergrund-Jobs des Users
killall -u $(whoami)

# Nginx graceful restart
killall -HUP nginx

# Alle Node.js-Prozesse älter als 1 Tag
killall -o 24h node

3 Prozessgruppen & Jobs

3.1 Vordergrund- und Hintergrundprozesse

Vordergrundprozess:

  • Blockiert das Terminal
  • Empfängt Tastatureingaben
  • Ctrl+C sendet SIGINT
  • Ctrl+Z sendet SIGTSTP (pausieren)

Hintergrundprozess:

  • Terminal bleibt nutzbar
  • Kein direkter Tastaturzugriff
  • Läuft parallel

Prozess im Hintergrund starten:

# Mit & am Ende
long-running-command &

# Beispiel
sleep 100 &
# [1] 12345   (Job-Nummer und PID)

Jobs verwalten:

# Alle Jobs anzeigen
jobs
# [1]  + running    sleep 100
# [2]  - running    another-command

# Mit PIDs
jobs -p

# Mit Status
jobs -l

Zwischen Vorder- und Hintergrund wechseln:

# Prozess starten
sleep 100

# Pausieren mit Ctrl+Z
^Z
# [1]  + 12345 suspended  sleep 100

# Im Hintergrund fortsetzen
bg
bg %1       # Bestimmter Job

# In den Vordergrund holen
fg
fg %1       # Bestimmter Job

Job-Referenzen:

ReferenzBedeutung
%1Job Nummer 1
%+ oder %%Aktueller Job
%-Vorheriger Job
%stringJob der mit “string” beginnt
%?stringJob der “string” enthält

Beispiele:

# Drei Jobs starten
sleep 100 &
vim file.txt &
python script.py &

# Jobs anzeigen
jobs
# [1]    running    sleep 100
# [2]  - running    vim file.txt
# [3]  + running    python script.py

# Vim in Vordergrund
fg %2
fg %vi       # Nach Name

# Python beenden
kill %3
kill %?python

3.2 nohup – Prozesse vom Terminal lösen

nohup (No Hangup) verhindert, dass ein Prozess beendet wird wenn das Terminal geschlossen wird.

Grundlegende Nutzung:

# Prozess startet und läuft nach Terminal-Schließung weiter
nohup command &

# Beispiel
nohup ./long-script.sh &
# nohup: ignoring input and appending output to 'nohup.out'

Ausgabe umleiten:

# Standard: Ausgabe geht nach nohup.out
nohup command &

# Eigene Log-Datei
nohup command > output.log 2>&1 &

# Ausgabe verwerfen
nohup command > /dev/null 2>&1 &

Typischer Workflow:

# 1. Prozess mit nohup starten
nohup ./backup.sh > backup.log 2>&1 &

# 2. PID notieren
echo $!
# 12345

# 3. Terminal schließen (Prozess läuft weiter)
exit

# 4. Später: Status prüfen
ps -p 12345
tail -f backup.log

Praktisches Beispiel:

# Langer Download
nohup wget -c https://example.com/large-file.zip > wget.log 2>&1 &

# Server starten
nohup python -m http.server 8000 > server.log 2>&1 &

# Backup-Skript
nohup rsync -avz /source/ /backup/ > rsync.log 2>&1 &

3.3 disown – Jobs aus Shell entfernen

disown entfernt einen Job aus der Job-Tabelle der Shell, sodass er nicht beendet wird wenn die Shell beendet wird.

Unterschied zu nohup:

Merkmalnohupdisown
ZeitpunktVor dem StartNach dem Start
SIGHUP ignorierenJaMit -h
Job-TabelleNormalEntfernt
Ausgabenohup.outUnverändert

Grundlegende Nutzung:

# Job starten
long-command &

# Aus Job-Tabelle entfernen
disown

# Bestimmten Job
disown %1

# SIGHUP ignorieren (Job bleibt in Liste)
disown -h %1

# Alle Jobs
disown -a

Typischer Workflow:

# 1. Prozess gestartet (vergessen nohup zu nutzen)
./script.sh
^Z
bg

# 2. Jetzt disown um ihn zu behalten
disown -h %1

# 3. Shell kann sicher beendet werden
exit

Praktisches Beispiel:

# Server versehentlich ohne nohup gestartet
python server.py &

# Oops! Terminal schließen würde Server beenden
# Lösung: disown
disown -h

# Jetzt sicher Terminal schließen
exit

Nachträglich von Terminal lösen:

# Prozess läuft im Vordergrund
long-running-process

# Ctrl+Z pausiert
^Z
# [1]  + suspended  long-running-process

# Im Hintergrund fortsetzen
bg

# Von Shell lösen
disown -h

# Terminal kann geschlossen werden

3.4 Prozessgruppen und Session-IDs

Konzepte:

Session (SID)
    └── Prozessgruppe (PGID)
            └── Prozess (PID)
            └── Prozess (PID)
    └── Prozessgruppe (PGID)
            └── Prozess (PID)
BegriffBeschreibung
PIDProcess ID – eindeutige Prozess-Kennung
PPIDParent PID – PID des Elternprozesses
PGIDProcess Group ID – Gruppe zusammengehöriger Prozesse
SIDSession ID – Login-Session

IDs anzeigen:

# Aktuelle IDs
echo "PID: $$"
echo "PPID: $PPID"

# Mit ps
ps -o pid,ppid,pgid,sid,comm

# Für bestimmten Prozess
ps -o pid,ppid,pgid,sid,comm -p 1234

Prozessgruppen verstehen:

# Pipeline erstellt Prozessgruppe
cat file | grep pattern | sort

# Alle drei Prozesse haben gleiche PGID
ps -o pid,pgid,comm
# PID   PGID  COMM
# 1001  1001  cat
# 1002  1001  grep
# 1003  1001  sort

Signal an Prozessgruppe senden:

# Negative PID = Prozessgruppe
kill -TERM -1001

# Alle Prozesse der Gruppe beenden
kill -9 -$(ps -o pgid= -p $PID)

Sessions verstehen:

  • Jedes Terminal startet eine neue Session
  • Session-Leader ist meist die Shell
  • Alle von der Shell gestarteten Prozesse gehören zur Session
# Neue Session erstellen (für Daemons)
setsid command

# Prozess von Terminal lösen
setsid ./daemon.sh

Prozessbaum anzeigen:

# Mit pstree (falls installiert)
brew install pstree
pstree

# Mit ps
ps -axjf

# Kinder eines Prozesses
pgrep -P 1234
ps --ppid 1234

Waisen- und Zombie-Prozesse:

TypBeschreibungStatus
WaiseElternprozess beendet, init übernimmtNormal
ZombieBeendet, aber Eltern hat Exit-Code nicht gelesenZ in ps
# Zombies finden
ps aux | awk '$8=="Z"'

# Oder
ps -eo pid,ppid,stat,comm | grep Z

Zombie-Prozesse bereinigen:

Zombies können nicht direkt beendet werden. Lösungen:

# 1. SIGCHLD an Elternprozess
kill -SIGCHLD $(ps -o ppid= -p $ZOMBIE_PID)

# 2. Elternprozess beenden (Zombie wird von init übernommen)
kill $(ps -o ppid= -p $ZOMBIE_PID)

# 3. Im schlimmsten Fall: Neustart

Daemon-Muster (doppelter Fork):

#!/bin/zsh
# daemon.sh - Prozess vollständig vom Terminal lösen

(
    # Erster Fork
    cd /
    umask 0
    exec setsid ./actual-daemon.sh &
) &

# Shell kann sofort beenden
exit 0

Zusammenfassung Job-Control:

# Starten
command &                    # Im Hintergrund
nohup command &              # Immun gegen SIGHUP

# Kontrolle
jobs                         # Jobs anzeigen
fg %n                        # In Vordergrund
bg %n                        # Im Hintergrund fortsetzen
Ctrl+Z                       # Pausieren
Ctrl+C                       # Abbrechen

# Loslösen
disown %n                    # Aus Job-Liste entfernen
disown -h %n                 # SIGHUP ignorieren

# Beenden
kill %n                      # Job beenden
kill -9 %n                   # Erzwungen