How to Find and Kill Zombie Processes on Linux Systems
In this mini post I’ll show you how to find and kill all zombie processes that may exist on your Linux Systems.
First, we need to define What is the Zombie process? and Why it exists?
A process is called a zombie process or defunct process if the process has been completed, but its PID and process entry remains in the Linux process table. A process is removed from the process table when the process is completed, and its parent process reads the completed process exit status by using the wait() system call. If a parent process fails to call wait() for whatever reason, its child process will be left in the process table, becoming a zombie.
How can we discover the existence of Zombie processes on Linux Systems?
Simply by using top
command, this will show the status of all processes running on your Linux System. run the following command and notice it’s output:
# top
top - 21:55:52 up 47 days, 22:12, 1 user, load average: 0.00, 0.04, 0.05
Tasks: 98 total, 2 running, 92 sleeping, 0 stopped, 4 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1883592 total, 312860 free, 889964 used, 680768 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 713172 avail Mem
From the above output, I’ve 4 zombie processes that completed their tasks and didn’t exit. It’s save to kill them, but first we need to list them.
How can we get the Zombie from process list…?
Its very simple. You can find out Zombie process with the following commands:
# ps aux |grep Z |grep -v grep USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2329 0.0 0.0 0 0 ? Zs Feb16 0:00 [systemctl] <defunct> root 4546 0.0 0.0 0 0 ? Zs Feb13 0:00 [systemctl] <defunct> root 16659 0.0 0.0 0 0 ? Zs 21:38 0:00 [systemctl] <defunct> root 26350 0.0 0.0 0 0 ? Zs Feb19 0:00 [systemctl] <defunct>
OR
# ps aux |grep "defunct" |grep -v grep USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2329 0.0 0.0 0 0 ? Zs Feb16 0:00 [systemctl] <defunct> root 4546 0.0 0.0 0 0 ? Zs Feb13 0:00 [systemctl] <defunct> root 16659 0.0 0.0 0 0 ? Zs 21:38 0:00 [systemctl] <defunct> root 26350 0.0 0.0 0 0 ? Zs Feb19 0:00 [systemctl] <defunct>
Now, we have the PID of the four zombie processes on our Linux System, let’s go and KILL THEM ALL using kill
command, go ahead and run this command:
# kill -9 2329 4546 16659 26350
Hooray, we killed the zombie process, let’s double check, by running any of the above command:
# ps aux |grep "defunct" |grep -v grep USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2329 0.0 0.0 0 0 ? Zs Feb16 0:00 [systemctl] <defunct> root 4546 0.0 0.0 0 0 ? Zs Feb13 0:00 [systemctl] <defunct> root 16659 0.0 0.0 0 0 ? Zs 21:38 0:00 [systemctl] <defunct> root 26350 0.0 0.0 0 0 ? Zs Feb19 0:00 [systemctl] <defunct>
Oh No, The Zombie Processes still exist on our Linux box, Kill command failed to kill them WHY?
Killing zombie processes is not obvious since zombie processes are already dead.
Hint:
1. A zombie process doesn’t react to signals.
How can we KILL the Zombie processes?
Simply, we have to kill it’s parent process. If the parent exited, the child would be orphaned and re-parented to init, which would immediately perform the wait(). In other words, they should go away once the parent process is done.
We need to find the PPID “the parent process ID” of the zombie processes using the following command and search for the zombie process PID:
# pstree -paul ..... ─monit,4647 -I │ ├─(systemctl,2329) │ ├─(systemctl,4546) │ ├─(systemctl,16659) │ ├─(systemctl,26350) │ └─{monit},464
In our example, the parent of the zombie process is the monit monitoring with PID 4647. Now we kill the monit process “the parent” to kill all it’s zombie processes, run the following command:
# kill -9 4647
Now, we check on the existence of ant zombie processes by using top
and ps
commands:
# top
op - 21:56:34 up 47 days, 22:13, 1 user, load average: 0.00, 0.04, 0.05
Tasks: 94 total, 1 running, 93 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.8 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1883592 total, 300796 free, 902092 used, 680704 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 701180 avail Mem
Hooray, zombie process count is ZERO,now ps
command check
# ps aux |grep Z |grep -v grep USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
No results found from ps command. We totally killed all our zombie processes.
Hint: If you didn't findpstree
command on your Linux, you need to install it. For Centos Linuxpstree
command exists in a package calledpsmisc
To install it runyum install psmisc
Finally, There is another way to kill the zombie processes without the need for pstree
command to get the parent process ID, we can get the PPID and PID of the zombie process using ps
command as follow:
# ps axo stat,ppid,pid,comm | grep -w defunct
ZN 3615 4472 single <defunct>
In this example, we only have one zombie process, as shown by ps
command, the parent process id of the zombie process is 3615.
To check the top command output, run
# top
top - 06:27:50 up 11 days, 20:10, 3 users, load average: 0.81, 1.01, 1.18
Tasks: 287 total, 1 running, 285 sleeping, 0 stopped, 1 zombie
%Cpu(s): 19.1 us, 2.1 sy, 0.0 ni, 78.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 16064460 total, 6182504 free, 5574520 used, 4307436 buff/cache
KiB Swap: 6279156 total, 5648764 free, 630392 used. 7962824 avail Mem
Indeed, we have one zombie process, now we kill it’s parent to kill it, run the following command:
# kill -9 3615
Now, we check
# ps axo stat,ppid,pid,comm | grep -w defunct
No output
# top
top - 06:33:40 up 11 days, 20:16, 3 users, load average: 1.36, 1.00, 1.10
Tasks: 288 total, 2 running, 286 sleeping, 0 stopped, 0 zombie
%Cpu(s): 19.4 us, 2.5 sy, 4.3 ni, 55.6 id, 18.0 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 16064460 total, 6316164 free, 5377196 used, 4371100 buff/cache
KiB Swap: 6279156 total, 5648772 free, 630384 used. 8239736 avail Mem
Also, no output
Before we leave this post, there are more commands you use to get the number of zombie processes on your Linux:
To Know How many Zombie process running on your server…?
# ps aux | awk {'print $8'}|grep -c Z 4 # ps aux | awk '{ print $8 " " $2 }' | grep -wc Z 4 # ps aux | awk {'print $8'}|grep Z|wc -l 4
Finally, I hope this mini post helped you.
AND DO NOT FORGET TO START THE MONIT PROCESS AGAIN “The one in the first example” As Monit do a good job on monitoring and starting services.
If You Appreciate What We Do Here On Mimastech, You Should Consider:
- Stay Connected to: Facebook | Twitter | Google+
- Support us via PayPal Donation
- Subscribe to our email newsletters.
- Tell other sysadmins / friends about Us - Share and Like our posts and services
We are thankful for your never ending support.