Radoslav Panev

SysAdmin and DevOps

Zombie process!!! Какво по дяволите!!!

07 Dec 2013 » FreeBSD, Linux

Зомби процесите са кофти работа, само заемат реуср от машинката
На всеки се е случвало или ако не ще му се случи да му зависне процес (наречен още zombie) чрез командата top може да видим дали имаме такива процеси и колко са те:

top

Пример:

top - 19:44:36 up 5 days, 15:16,  2 users,  load average: 0.00, 0.02, 0.00
Tasks: 196 total,   1 running, 195 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.1%us,  0.1%sy,  0.0%ni, 99.7%id,  0.1%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4826536k total,  2355544k used,  2470992k free,   150336k buffers
Swap: 12582904k total,        0k used, 12582904k free,  1784852k cached

На вторият ред се вижда, че в случая имаме 0 zombi (зависнали процеси). Ако се появи такъв процес той трябва да бъде kill-нат защото товари само машината излишно. Това може да стане по следният начин използвайки една от двете команди :

ps -elf | grep Z

или

ps aux | awk '{ print $8 " " $2 }' | grep -w Z

След което просто kill-ваме процесите по PID🙂 или по името на процеса примерно :

ps aux | grep httpd | kill `awk '{print $2}'`

Въпросната команда обикаля дървото с процесите и навсякъде където срещне думата “httpd” kill-ва процеса.

Ето и един скрипт за kill-ването на всички зомби процеси (copy/paste) 🙂

#!/bin/bash
##################################################################
# Script: Zombie Slayer
# Author: Mitch Milner
# Date:   03/13/2013 ---> A good day to slay zombies
#
# Requirements: yum install gdb
#               permissions to attach to the parent process
#
# This script works by using a debugger to
# attach to the parent process and then issuing
# a waitpid to the dead zombie. This will not kill
# the living parent process.
##################################################################

clear
# Wait for user input to proceed, give user a chance to cancel script
echo "***********************************************************"
echo -e "This script will terminate all zombie process."
echo -e "Press [ENTER] to continue or [CTRL] + C to cancel:"
echo "***********************************************************"
read cmd_string
echo -e "\n"

# initialize variables
intcount=0
lastparentid=0

# remove old gdb command file
rm -f /tmp/zombie_slayer.txt

# create the gdb command file
echo "***********************************************************"
echo "Creating command file..."
echo "***********************************************************"
ps -e -o ppid,pid,stat,command | grep Z | sort | while read LINE; do
  intcount=$((intcount+1))
  parentid=`echo $LINE | awk '{print $1}'`
  zombieid=`echo $LINE | awk '{print $2}'`
  verifyzombie=`echo $LINE | awk '{print $3}'`

  # make sure this is a zombie file and we are not getting a Z from
  # the command field of the ps -e -o ppid,pid,stat,command
  if [ "$verifyzombie" == "Z" ]
  then
    if [ "$parentid" != "$lastparentid" ]
    then
      if [ "$lastparentid" != "0" ]
      then
        echo "detach" >> /tmp/zombie_slayer.txt
      fi
    echo "attach $parentid" >> /tmp/zombie_slayer.txt
    fi
    echo "call waitpid ($zombieid,0,0)" >> /tmp/zombie_slayer.txt
    echo "Logging: Parent: $parentid  Zombie: $zombieid"
    lastparentid=$parentid
  fi
done
if [ "$lastparentid" != "0" ]
then
  echo "detach" >> /tmp/zombie_slayer.txt
fi

# Slay the zombies with gdb and the created command file
echo -e "\n\n"
echo "***********************************************************"
echo "Slaying zombie processes..."
echo "***********************************************************"
gdb -batch -x /tmp/zombie_slayer.txt
echo -e "\n\n"
echo "***********************************************************"
echo "Script complete."
echo "***********************************************************"