mysql僵尸进程_僵尸Z进程和D进程
-------------- 1 關于ZOMBIE進程:
# ps -el| grep Z
F S?? UID?? PID? PPID? C PRI? NI ADDR SZ WCHAN? TTY????????? TIME CMD
0 Z???? 0? 3288? 3278? 0? 80?? 0 -???? 0 exit?? ???????? 00:00:00 sh
0 Z???? 0? 7289? 7282? 0? 80?? 0 -???? 0 exit?? ???????? 00:00:00 sh
0 Z???? 0? 9862? 9856? 0? 80?? 0 -???? 0 exit?? ???????? 00:00:00 sh
# ps -ef |grep defunct
root????? 3288? 3278? 0 Feb19 ???????? 00:00:00 [sh]
root????? 3789? 1710? 0 17:05 pts/8??? 00:00:00 grep defunct
root????? 7289? 7282? 0 07:11 ???????? 00:00:00 [sh]
root????? 9862? 9856? 0 Feb26 ???????? 00:00:00 [sh]
這些進程已經死亡,但沒有釋放系統資源,包括內存和一些一些系統表等, 如果這樣的進程很多,會引發系統問題。用ps -el看出的進程狀態如果是Z,就是僵尸進程。
Z 之所以殺不死,是因為它已經死了,否則怎么叫 Zombie(僵尸)呢?冤魂不散,自然是生前有結未解之故。在UNIX/Linux中,每個進程都有一個父進程,進程號叫PID(Process ID),相應地,父進程號就叫PPID(Parent PID)。當進程死亡時,它會自動關閉已打開的文件,舍棄已占用的內存、交換空間等等系統資源,然后向其父進程返回一個退出狀態值,報告死訊。如果程序有 bug,就會在這最后一步出問題。兒子說我死了,老子卻沒聽見,沒有及時收棺入殮,兒子便成了僵尸。在UNIX/Linux中消滅僵尸的手段比較殘忍,執 行 ps axjf 找出僵尸進程的父進程號(PPID,第一列),先殺其父,然后再由進程天子 init(其PID為1,PPID為0)來一起收拾父子僵尸,超度亡魂,往生極樂。注意,子進程變成僵尸只是礙眼而已,并不礙事,如果僵尸的父進程當前有 要務在身,則千萬不可貿然殺之。
清除ZOMBIE(僵尸)進程可以使用如下方法:
1> kill –18 PPID (PPID是其父進程)
這個信號是告訴父進程,該子進程已經死亡了,請收回分配給他的資源。
2>如 果不行則看能否終止其父進程(如果其父進程不需要的話)。先看其父進程又無其他子進程,如果有,可能需要先kill其他子進程,也就是兄弟進程。方法是:
kill –15 PID1 PID2(PID1,PID2是僵尸進程的父進程的其它子進程)。
然后再kill父進程:kill –15 PPID
這 樣僵尸進程就可能被完全殺掉了。
ps alx | grep 17191
lsof -p 進程ID
pstree -p 進程ID
ps -p 進程ID
詳細信息查看:
/proc/[PID]/stat
[root@localhost ~]# cat /proc/6873/stat
6873 (a.out) R 6723 6873 6723 34819 6873 8388608 77 0 0 0 41958 31 0 0 25 0 3 0 5882654 1409024 56 4294967295 134512640 134513720 3215579040 0 2097798 0 0 0 0 0 0 0 17 0 0 0 [root@localhost ~]#
每個參數意思為:
參數 解釋
pid=6873 進程(包括輕量級進程,即線程)號
comm=a.out 應用程序或命令的名字
task_state=R 任務的狀態,R:runnign, S:sleeping (TASK_INTERRUPTIBLE), D:disk sleep (TASK_UNINTERRUPTIBLE), T: stopped, T:tracing stop,Z:zombie, X:dead
ppid=6723 父進程ID
pgid=6873 線程組號
sid=6723 c該任務所在的會話組ID
tty_nr=34819(pts/3) 該任務的tty終端的設備號,INT(34817/256)=主設備號,(34817-主設備號)=次設備號
tty_pgrp=6873 終端的進程組號,當前運行在該任務所在終端的前臺任務(包括shell 應用程序)的PID。
task->flags=8388608 進程標志位,查看該任務的特性
min_flt=77 該任務不需要從硬盤拷數據而發生的缺頁(次缺頁)的次數
cmin_flt=0 累計的該任務的所有的waited-for進程曾經發生的次缺頁的次數目
maj_flt=0 該任務需要從硬盤拷數據而發生的缺頁(主缺頁)的次數
cmaj_flt=0 累計的該任務的所有的waited-for進程曾經發生的主缺頁的次數目
utime=1587 該任務在用戶態運行的時間,單位為jiffies
stime=1 該任務在核心態運行的時間,單位為jiffies
cutime=0 累計的該任務的所有的waited-for進程曾經在用戶態運行的時間,單位為jiffies
cstime=0 累計的該任務的所有的waited-for進程曾經在核心態運行的時間,單位為jiffies
priority=25 任務的動態優先級
nice=0 任務的靜態優先級
num_threads=3 該任務所在的線程組里線程的個數
it_realvalue=0 由于計時間隔導致的下一個 SIGALRM 發送進程的時延,以 jiffy 為單位.
start_time=5882654 該任務啟動的時間,單位為jiffies
vsize=1409024(page) 該任務的虛擬地址空間大小
rss=56(page) 該任務當前駐留物理地址空間的大小
Number of pages the process has in real memory,minu 3 for administrative purpose.
這些頁可能用于代碼,數據和棧。
rlim=4294967295(bytes) 該任務能駐留物理地址空間的最大值
start_code=134512640 該任務在虛擬地址空間的代碼段的起始地址
end_code=134513720 該任務在虛擬地址空間的代碼段的結束地址
start_stack=3215579040 該任務在虛擬地址空間的棧的結束地址
kstkesp=0 esp(32 位堆棧指針) 的當前值, 與在進程的內核堆棧頁得到的一致.
kstkeip=2097798 指向將要執行的指令的指針, EIP(32 位指令指針)的當前值.
pendingsig=0 待處理信號的位圖,記錄發送給進程的普通信號
block_sig=0 阻塞信號的位圖
sigign=0 忽略的信號的位圖
sigcatch=082985 被俘獲的信號的位圖
wchan=0 如果該進程是睡眠狀態,該值給出調度的調用點
nswap 被swapped的頁數,當前沒用
cnswap 所有子進程被swapped的頁數的和,當前沒用
exit_signal=17 該進程結束時,向父進程所發送的信號
task_cpu(task)=0 運行在哪個CPU上
task_rt_priority=0 實時進程的相對優先級別
task_policy=0 進程的調度策略,0=非實時進程,1=FIFO實時進程;2=RR實時進程
這類進程是有問題的. 需要回收資源.
在unix程序設計的一本書里印像有一種情況會出現這樣的進程.
主程序fork出的子進程結束之后. 父進程沒有釋放子進程所占用的資源. 這時這個進程就一直是zombie狀態.
---- 百科:
ZOMBIE:僵尸狀態,表示進程結束但尚未消亡的一種狀態,此時進程已經結束運行并釋放大部分資源,但尚未釋放進程控制塊。
與ZOMBIE對應的進程狀態還有RUNNING(正在運行或等待運行狀態),UNINTERRUPTABLE(不可中斷阻塞狀態),INTERRUPTABLE(可中斷阻塞狀態),STOPPED(掛起狀態)。
服務器通常都會帶來一些僵尸進程,占用系統資源,浪費資源等,一般我們使用top命令就可以看得出來,如圖:
(可以看到,我的服務器已經產生了兩個僵尸進程)
解決方法:
#ps -A -o stat,ppid,pid,cmd |grep -e "^[Zz]" //先查看具體進程:
#lsof -p ppid;
#lsof -p pid;
#kill -9 pid號 //殺死z進程(這些動作是比較危險的,希望在真正的服務器上面慎用!!!)
假若你的z進程比較多,可以編寫個小小的腳本,下面是參與網上的
#ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' | awk '{print $2}' | xargs kill
首先,我們可以用top命令來查看服務器當前是否有僵尸進程,可以看到第二行行尾有個 0 zombie,如果數字大于0,那么意味著服務器當前存在有僵尸進程? 可以用ps和grep命令尋找僵尸進程
ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'
命令選項說明:
-A 參數列出所有進程
-o 自定義輸出字段 我們設定顯示字段為 stat(狀態), ppid(進程父id), pid(進程id),cmd(命令)這四個參數
因為狀態為 z或者Z的進程為僵尸進程,所以我們使用grep抓取stat狀態為zZ進程
運行結果參考如下
Z 12334 12339 /path/cmd
這時,我們可以使用 kill -HUP 12339來殺掉這個僵尸進程
運行后,可以再次運行ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'來確認是否將僵尸進程殺死
如果kill 子進程的無效,可以嘗試kill 其父進程來解決問題,例如上面例子父進程pid是 12334,那么我們就運行
kill -HUP 12334來解決問題
----
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}'
執行上面獲得的語句即可, 使用信號量9, 僵尸進程數會大大減少.
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
發現僵尸進程數減少了一些, 但還有不少啊.
4) 再次獲得殺僵尸進程語句
# ps -ef | grep defunct | grep -v grep | awk '{print "kill -18 " $3}'
執行上面獲得的語句即可, 這次使用信號量18殺其父進程, 僵尸進程應該會全部消失.
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是其父進程, 這個信號是告訴父進程, 該子進程已經死亡了, 請收回分配給他的資源. 如果還不行則看先看其父進程又無其他子進程, 如果有, 可能需要先kill其他子進程, 也就是兄弟進程.
方法是:
# kill -15 PID1 PID2
PID1,PID2是僵尸進程的父進程的其它子進程.
然后再kill父進程:
# kill -15 PPID
=======================2? Linux進程的Uninterruptible sleep(D)狀態
D,往往是由于 I/O 資源得不到滿足,而引發等待,在內核源碼 fs/proc/array.c 里,其文字定義為“ "D (disk sleep)", /* 2 */ ”(由此可知 D 原是Disk的打頭字母),對應著 include/linux/sched.h 里的“ #define TASK_UNINTERRUPTIBLE 2 ”。舉個例子,當 NFS 服務端關閉之時,若未事先 umount 相關目錄,在 NFS 客戶端執行 df 就會掛住整個登錄會話,按 Ctrl+C 、Ctrl+Z 都無濟于事。斷開連接再登錄,執行 ps axf 則看到剛才的 df 進程狀態位已變成了 D ,kill -9 無法殺滅。正確的處理方式,是馬上恢復 NFS 服務端,再度提供服務,剛才掛起的 df 進程發現了其苦苦等待的資源,便完成任務,自動消亡。若 NFS 服務端無法恢復服務,在 reboot 之前也應將 /etc/mtab 里的相關 NFS mount 項刪除,以免 reboot 過程例行調用 netfs stop 時再次發生等待資源,導致系統重啟過程掛起。
運行在KVM虛擬機里的一些進程突然出了問題,這些出了問題的進程無法用kill殺掉,使用ps可以看到這些進程處于D狀 態:
[build@kbuild-john ~]$ ps -a -ubuild -o pid,ppid,stat,command
PID? PPID STAT COMMAND
17009???? 1 Ds?? -bash
17065???? 1 D??? ls --color=tty -al
17577???? 1 D??? /usr/java/jdk1.5.0_17/bin/java -Xmx512m -classpath /usr/local/a
17629???? 1 D??? /usr/java/jdk1.5.0_17/bin/java -Xmx512m -classpath /usr/local/a
ps 的手冊里說D狀態是uninterruptible sleep,Linux進程有兩種睡眠狀態,一種interruptible sleep,處在這種睡眠狀態的進程是可以通過給它發信號來喚醒的,比如發HUP信號給nginx的master進程可以讓nginx重新加載配置文件而 不需要重新啟動nginx進程;另外一種睡眠狀態是uninterruptible sleep,處在這種狀態的進程不接受外來的任何信號,這也是為什么之前我無法用kill殺掉這些處于D狀態的進程,無論是”kill”, “kill -9″還是”kill -15″,因為它們壓根兒就不受這些信號的支配。
進程為什么會被置于uninterruptible sleep狀態呢?處于uninterruptible sleep狀態的進程通常是在等待IO,比如磁盤IO,網絡IO,其他外設IO,如果進程正在等待的IO在較長的時間內都沒有響應,那么就很會不幸地被 ps看到了,同時也就意味著很有可能有IO出了問題,可能是外設本身出了故障,也可能是比如掛載的遠程文件系統已經不可訪問了,我這里遇到的問題就是由 down掉的NFS服務器引起的。
正是因為得不到IO的相應,進程才進入了uninterruptible sleep狀態,所以要想使進程從uninterruptible sleep狀態恢復,就得使進程等待的IO恢復,比如如果是因為從遠程掛載的NFS卷不可訪問導致進程進入uninterruptible sleep狀態的,那么可以通過恢復該NFS卷的連接來使進程的IO請求得到滿足,除此之外,要想干掉處在D狀態進程就只能重啟整個Linux系統了。
看到有人說如果要想殺掉D狀態的進程,通常可以去殺掉它的父進程(通常是shell,我理解的這種情況是在shell下直接運行的該進程,之后該進 程轉入了D狀態),于是我就照做了,之后就出現了上面的狀態:他們的父進程被殺掉了,但是他們的父進程PID都變成了1,也就是init進程,這下可如何是好?此時我這些D狀態的進程已經影響到其他一些進程的運行,而已經無法訪問的NFS卷又在段時間內無法恢復,那么,只好重新啟動了,root不是玉皇大 帝,也有無奈的時候。
總結
以上是生活随笔為你收集整理的mysql僵尸进程_僵尸Z进程和D进程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么从视频中提取音频,这四个方法简单实用
- 下一篇: box-shadow页面立体效果