Eines der lästigsten Probleme auf Linux-Servern sind Zombie-Prozesse. Wenn ein Prozess beendet ist, aber immer noch Platz in der Prozesstabelle belegt, wird er als Zombie bezeichnet. Dies kann sich besonders auf lang laufenden Servern ansammeln und Probleme verursachen. Wie kann man Zombie-Prozesse bereinigen? Schauen wir es uns Schritt für Schritt an.
Was sind Zombie-Prozesse und warum entstehen sie?
Ein Zombie-Prozess ist eigentlich ein vollständig beendeter Prozess, der jedoch noch vom System gehalten wird, weil der Elternprozess keinen wait()-Aufruf durchgeführt hat. Wenn Sie beispielsweise einen Webserver betreiben, wird für jede Verbindung ein neuer Prozess erstellt. Wenn dieser Prozess beendet ist, muss der Elternprozess seinen Exit-Status auslesen. Tut der Elternprozess dies nicht, wird der Prozess zum Zombie. Das System zeigt dies in der ps-Ausgabe mit einem 'Z' an.
Auf den ersten Blick scheinen Zombies harmlos, aber mit zunehmender Anzahl können sie den PID-Pool (Process ID) erschöpfen. Die Anzahl der PIDs im System ist begrenzt (normalerweise durch /proc/sys/kernel/pid_max festgelegt, standardmäßig 32768). Wird dieses Limit erreicht, können keine neuen Prozesse mehr erstellt werden, und der Server kann zum Stillstand kommen.
Erkennung von Zombie-Prozessen
Um Zombie-Prozesse zu sehen, verwenden Sie im Terminal folgenden Befehl:
ps aux | grep ZOder für eine detailliertere Liste:
ps -eo pid,stat,cmd | grep ZDieser Befehl zeigt Ihnen die PID und den Befehl der Zombie-Prozesse an. Außerdem können Sie in der top-Ausgabe die Spalte Z sehen. Wenn sich auf einem Server beispielsweise 50 Zombie-Prozesse angesammelt haben, ist das ein Alarmzeichen.
Eine weitere Methode ist die Untersuchung des /proc-Dateisystems. Zombie-Prozesse sind immer noch unter /proc vorhanden, aber die meisten Informationen sind leer. Mit dem folgenden Befehl können Sie deutlicher sehen, welche Prozesse Zombies sind:
cat /proc/[pid]/status | grep StateErsetzen Sie [pid] durch die PID des entsprechenden Prozesses. Wenn in der Ausgabe ein Z (zombie) steht, sind Sie auf dem richtigen Weg.
Manuelle Bereinigungsmethoden
Sie können Zombie-Prozesse nicht direkt töten, da sie bereits tot sind. Der Weg, sie zu bereinigen, besteht darin, den Elternprozess zum Warten zu bewegen. Dafür gibt es drei grundlegende Methoden:
1. Elternprozess beenden
Die sicherste Lösung ist, den Elternprozess des Zombies zu beenden. Wenn der Elternprozess stirbt, werden die Zombie-Prozesse von init (PID 1) übernommen, und init ruft sofort wait() auf, um sie zu bereinigen. Dafür:
kill -9 [parent_pid]Dies kann jedoch riskant sein, da der Elternprozess möglicherweise mehrere Kindprozesse verwaltet, die dann alle verloren gehen. Wenn Sie beispielsweise den Elternprozess eines Apache-Webservers töten, werden alle Verbindungen unterbrochen.
2. SIGCHLD-Signal senden
Durch Senden des SIGCHLD-Signals an den Elternprozess können Sie ihn veranlassen, die Status der wartenden Kindprozesse auszulesen. Die meisten Prozesse führen bei Erhalt dieses Signals wait() aus. Befehl:
kill -SIGCHLD [parent_pid]Diese Methode ist sanfter. Allerdings verarbeiten einige Programme dieses Signal nicht korrekt, sodass es nicht immer funktioniert.
3. Eingriff mit GDB
Eine fortgeschrittene Methode ist die Verwendung von gdb, um sich mit dem Elternprozess zu verbinden und direkt einen wait()-Aufruf durchzuführen. Zum Beispiel:
gdb -p [parent_pid]call waitpid([zombie_pid], 0, 0)
quit
Diese Methode ist etwas gefährlich und wird auf Live-Systemen nicht empfohlen, kann aber in Notfällen hilfreich sein.
Automatische Bereinigung und Vorbeugung
Der beste Weg, die Ansammlung von Zombie-Prozessen zu verhindern, ist die korrekte Verwendung von wait() oder waitpid() in der Programmierung. Bei vorhandener Software können wir dies jedoch nicht ändern. Stattdessen:
Ein Watchdog-Skript erstellen
Schreiben Sie ein periodisch laufendes Bash-Skript, das Zombie-Prozesse erkennt und SIGCHLD an deren Elternprozesse sendet. Zum Beispiel:
#!/bin/bashzombies=$(ps aux | grep ' Z ' | awk '{print $2}')
for pid in $zombies; do
ppid=$(ps -o ppid= -p $pid)
kill -SIGCHLD $ppid 2>/dev/null
done
Fügen Sie dieses Skript in den Crontab ein, damit es alle 5 Minuten ausgeführt wird:
*/5 * * * * /usr/local/bin/zombie_cleaner.shSystemeinstellungen ändern
In der Datei /etc/security/limits.conf können Sie die Anzahl der Prozesse pro Benutzer begrenzen. Außerdem können Sie den Wert kernel.pid_max erhöhen, um den PID-Pool zu erweitern:
echo 65536 > /proc/sys/kernel/pid_maxDies ist jedoch eine temporäre Lösung; die eigentliche Ursache sollte behoben werden.
Dienstverwaltung mit systemd
Wenn die Zombie-Prozesse von einem systemd-Dienst stammen, können Sie die KillMode-Einstellung des Dienstes von process auf cgroup ändern, um alle Kindprozesse zu bereinigen. Fügen Sie dem Dienst Folgendes hinzu:
[Service]KillMode=process
Starten Sie den Dienst anschließend neu.
Fazit
Zombie-Prozesse sind zwar nicht sehr beängstigend, können sich aber ansammeln und Ihren Server lahmlegen. Überprüfen Sie Ihr System regelmäßig mit ps und top. Wenn eine Anwendung ständig Zombies erzeugt, melden Sie dies dem Entwickler. Vergessen Sie nicht, in Ihren eigenen Skripten wait() zu verwenden. Denken Sie daran: Ein sauberer Server ist ein glücklicher Server!