linux 如何殺死僵尸進程
Posted on 2011 年 9 月 20 日 by Open-Source
In UNIX System terminology, a process that has terminated,but whose parent has not yet waited for it, is called a zombie.
在UNIX 系統(tǒng)中,一個進程結(jié)束了,但是他的父進程沒有等待(調(diào)用wait / waitpid)他, 那么他將變成一個僵尸進程. 在fork()/execve()過程中,假設(shè)子進程結(jié)束時父進程仍存在,而父進程fork()之前既沒安裝SIGCHLD信號處理函數(shù)調(diào)用 waitpid()等待子進程結(jié)束,又沒有顯式忽略該信號,則子進程成為僵尸進程。
如何查看linux系統(tǒng)上的僵尸進程,如何統(tǒng)計有多少僵尸進程?
#ps -ef | grep defunct
或者查找狀態(tài)為Z的進程,Z就是代表zombie process,僵尸進程的意思。
另外使用top命令查看時有一欄為S,如果狀態(tài)為Z說明它就是僵尸進程。
Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie
top命令中也統(tǒng)計了僵尸進程?;蛘呤褂孟旅娴拿睿?/p>
ps -ef | grep defunct | grep -v grep | wc -l
如何殺死僵尸進程呢?
一般僵尸進程很難直接kill掉,不過您可以kill僵尸爸爸。父進程死后,僵尸進程成為”孤兒進程”,過繼給1號進程init,init始終會負責清理僵尸進程.它產(chǎn)生的所有僵尸進程也跟著消失。
ps -e -o ppid,stat | grep Z | cut -d” ” -f2 | xargs kill -9
或
kill -HUP `ps -A -ostat,ppid | grep -e ’^[Zz]‘ | awk ’{print $2}’`
當然您可以自己編寫更好的shell腳本,歡迎與大家分享。
另外子進程死后,會發(fā)送SIGCHLD信號給父進程,父進程收到此信號后,執(zhí)行waitpid()函數(shù)為子進程收尸。就是基于這樣的原理:就算父進程沒有調(diào)用wait,內(nèi)核也會向它發(fā)送SIGCHLD消息,而此時,盡管對它的默認處理是忽略,如果想響應(yīng)這個消息,可以設(shè)置一個處理函數(shù)。
如何避免僵尸進程呢?
處理SIGCHLD信號并不是必須的。但對于某些進程,特別是服務(wù)器進程往往在請求到來時生成子進程處理請求。如果父進程不等待子進程結(jié) 束,子進程將成為僵尸進程(zombie)從而占用系統(tǒng)資源。如果父進程等待子進程結(jié)束,將增加父進程的負擔,影響服務(wù)器進程的并發(fā)性能。在Linux下 可以簡單地將 SIGCHLD信號的操作設(shè)為SIG_IGN。
signal(SIGCHLD,SIG_IGN);
這樣,內(nèi)核在子進程結(jié)束時不會產(chǎn)生僵尸進程。這一點與BSD4不同,BSD4下必須顯式等待子進程結(jié)束才能釋放僵尸進程
或者
用兩次fork(),而且使緊跟的子進程直接退出,是的孫子進程成為孤兒進程,從而init進程將負責清除這個孤兒進程
示例:
1) 檢查當前僵尸進程信息
# ps -ef | grep defunct | grep -v grep | wc -l
175
# top | head -2
top - 15:05:54 up 97 days, 23:49, 4 users, load average: 0.66, 0.45, 0.39
Tasks: 829 total, 1 running, 479 sleeping, 174 stopped, 175 zombie
# ps -ef | grep defunct | grep -v grep
2) 獲得殺僵尸進程語句
# ps -ef | grep defunct | grep -v grep | awk '{print "kill -9 " $2,$3}'
執(zhí)行上面獲得的語句即可, 使用信號量9, 僵尸進程數(shù)會大大減少.
3) 過一會兒檢查當前僵尸進程信息
# ps -ef | grep defunct | grep -v grep | wc -l
125
# top | head -2
top - 15:29:26 up 98 days, 12 min, 7 users, load average: 0.27, 0.54, 0.56
Tasks: 632 total, 1 running, 381 sleeping, 125 stopped, 125 zombie
現(xiàn)僵尸進程數(shù)減少了一些, 但還有不少啊.
4) 再次獲得殺僵尸進程語句
# ps -ef | grep defunct | grep -v grep | awk '{print "kill -18 " $3}'
執(zhí)行上面獲得的語句即可, 這次使用信號量18殺其父進程, 僵尸進程應(yīng)該會全部消失.
5) 過一會兒再檢查當前僵尸進程信息
# ps -ef | grep defunct | grep -v grep | wc -l
0
# top | head -2
top - 15:39:46 up 98 days, 23 min, 7 users, load average: 5.46, 2.20, 1.12
Tasks: 134 total, 1 running, 133 sleeping, 0 stopped, 0 zombie
6) 清除ZOMBIE(僵尸)進程原理
# kill -18 PPID
PPID是其父進程, 這個信號是告訴父進程, 該子進程已經(jīng)死亡了, 請收回分配給他的資源. 如果還不行則看先看其父進程又無其他子進程, 如果有, 可能需要先kill其他子進程, 也就是兄弟進程.
是:
# kill -15 PID1 PID2
PID1,PID2是僵尸進程的父進程的其它子進程.
然后再kill父進程:
# kill -15 PPID