Wanneer je een Linux-systeem monitort met de top opdracht, kun je soms een regel in de 'taken (Tasks)' tegenkomen zoals 1 zombie (zombie).

top - 16:03:19 up 7:09, 1 gebruiker, gemiddelde belasting: 2.24, 2.21, 2.29
Taken: 392 totaal, 1 in uitvoering, 390 wachtend, 0 gestopt, 1 zombie
...

Wat is deze 'zombie' en welke impact heeft het op het systeem? In deze post leggen we duidelijk de identiteit van het zombieproces en hoe dit te identificeren en op te lossen uit.


Wat is een Zombieproces? 🧟



Laten we het vergelijken met de levenscyclus van een proces om het begrijpelijk te maken.

  1. Geboren (Fork): het ouders proces (Parent Process) creëert een kind proces (Child Process) (fork()).

  2. Uitvoeren (Exec): het kind proces voert zijn taak uit.

  3. Beeindigen (Exit): het kind proces voltooit zijn taak en beëindigt (exit()).

  4. Oogsten (Wait): wanneer het kind proces beëindigt, slaat het besturingssysteem (kernel) informatie zoals de PID van het proces en de beëindigingsstatus op in de proces tafel. Vervolgens stuurt het een SIGCHLD signaal naar het ouders proces (het kind is beëindigd).

  5. Het ouders proces ontvangt dit signaal en moet de wait() systeemoproep aanroepen om de beëindigingsstatus van het kind "te oogsten". Pas wanneer deze informatie is geoogst, kan de kernel het item van het kind definitief uit de proces tafel verwijderen.

Een zombieproces is dus een proces dat vastzit tussen stap 4 en 5. Dit betekent dat het kind proces is beëindigd, maar het ouders proces heeft nog niet de wait() aanroep gedaan om de beëindigingsstatus te oogsten.

Zoals de naam al aangeeft, is dit proces in een dode staat (niet uitgevoerd). Het verbruikt daarom geen systeemresources zoals CPU of geheugen.

Waarom zijn zombieprocessen een probleem?

Zombieprocessen gebruiken zelf bijna geen systeemresources, maar ze bezetten wel een slot (PID) in de proces tafel.

Als er door een bug in het ouders proces zombieprocessen blijven stapelen zonder opgeruimd te worden, kan het maximum aantal PID's dat het systeem kan toewijzen bereikt worden. In dat geval kan het systeem geen nieuwe processen meer aanmaken, wat kan leiden tot ernstige storingen. Het is niet ongebruikelijk dat 1-2 zombies zichtbaar zijn in top, maar als dit aantal blijft toenemen, is actie vereist.


Hoe zombieprocessen te identificeren en te herkennen

De top opdracht toont alleen het _aantal_ zombies. Om te zien welk proces in de zombie-status is en wie de ouder is, moet je de ps opdracht gebruiken.

De eenvoudigste manier is om het STAT (status) veld van de ps opdracht te bekijken en te zoeken naar processen die gemarkeerd zijn met 'Z'.

# Bekijk alle processen in het systeem en filter voor status 'Z' (zombie)
ps -elf | grep ' Z '

# Of gebruik de 'aux' optie (de 8e kolom ($8) is de status (STAT))
ps aux | awk '$8=="Z"'

Voorbeeld output:

# ps -elf | grep ' Z '
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
0 Z  user  5021  5000  0  80   0 -     0 exit   15:30 ?        00:00:00 [defunct]

Belangrijke informatie uit het bovenstaande voorbeeld is:

  • S (Status): Z (betekent dat het in zombie status is)

  • PID: 5021 (dit is de PID van het zombieproces)

  • PPID: 5000 (dit is de PID van het ouder proces dat niet heeft geoogst)

  • CMD: [defunct] (de naam die aangeeft dat het is beëindigd maar niet is opgeruimd)


Hoe zombieprocessen op te lossen



Het belangrijkste om te weten is dat je een zombieproces niet kunt 'doden' met het kill commando.

kill -9 5021 (de zombie PID uit het bovengenoemde voorbeeld)

Dit commando werkt niet. Zombies zijn al in een "dode" staat. Er is niemand meer om het kill signaal te verwerken.

De enige manier om zombieprocessen op te lossen is door het ouders proces te laten wait() aanroepen.

Stap 1: Signaal naar het ouders proces sturen (aanbevolen)

De eerste stap die je kunt proberen, is het handmatig versturen van een SIGCHLD signaal naar het ouders proces (PPID) om hem te vragen de status van het kind te controleren.

# Stuur een SIGCHLD signaal naar het ouders PID (5000) uit het bovengenoemde voorbeeld
kill -s SIGCHLD 5000

Dit heeft het effect dat het ouders proces ontvangt "Een van jouw kind processen is beëindigd, kijk ernaar!". Normaal gesproken zal een goed geprogrammeerd ouders proces deze signaal ontvangen en de zombie opruimen.

Stap 2: Dood het ouders proces (laatste redmiddel)

Als stap 1 niet werkt, betekent dit dat het ouders proces (PPID 5000) zelf is vastgelopen of dat er een ernstige bug zit in de logica die wait() aanroept.

In dit geval is het doden van het ouders proces de enige oplossing.

# Dood het ouders proces (PPID 5000)
kill 5000

# Als het nog steeds niet stopt, gebruik dan geforceerd
kill -9 5000

Waarom lost het op als je de ouder doodt?

In Linux, wanneer een ouders proces sterft, worden de kind processen (weesprocessen) automatisch init proces (PID 1) of systemd geadopteerd. Het init proces is ontworpen om regelmatig de status van zijn kinderen te controleren en beëindigde kinderen (inclusief zombies) onmiddellijk op te ruimen.

Daarom, als de problematische ouder (PPID 5000) sterft, wordt de zombie (PID 5021) het nieuwe kind van init en zal init het onmiddellijk opruimen.

⚠️ Opmerking: Controleer vóór het beëindigen van het ouders proces met ps -p 5000 of dit proces geen belangrijke service in het systeem is (bijv. DB, webserver, enz.). Het geforceerd beëindigen van belangrijke services kan leiden tot grotere storingen.


Samenvatting

  • Zombieprocessen zijn resten van processen die zijn beëindigd maar waarvan de ouder de beëindigingsstatus niet heeft geoogst.

  • Ze verbruiken geen resources, maar bezetten een PID, en als ze in overmaat verschijnen, kunnen ze systeemstoringen veroorzaken.

  • ps -elf | grep ' Z ' opdracht kan gebruikt worden om de zombie (PID) en zijn ouder (PPID) te vinden.

  • De oplossing richt zich niet op de zombie, maar op de ouder proces (PPID).

    1. kill -s SIGCHLD <ouderPID> (aanbevolen)

    2. kill <ouderPID> (laatste redmiddel)