- 积分
- 16843
在线时间 小时
最后登录1970-1-1
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?开始注册
x
在维护服务器的时候,发现有多个nova-novncproxy的僵尸进程。* N) L. L0 b2 p( s
; k4 Q- o$ }/ [8 B( E26327 ? S 0:05 \_ /usr/bin/python /usr/bin/nova-novncproxy --config-file=/etc/nova/nova.conf: r, k. y! @4 a% R% {( F$ L7 O0 x
4765 ? Z 0:00 \_ [nova-novncproxy] <defunct>
- I# Z8 `2 A2 }4 a 4766 ? Z 0:00 \_ [nova-novncproxy] <defunct>
/ q( o4 f# y6 c 4767 ? Z 0:00 \_ [nova-novncproxy] <defunct>
1 u- V l$ h1 h 4768 ? Z 0:00 \_ [nova-novncproxy] <defunct>
5 y6 f# w! M7 b. |4 z7 j( Z 4769 ? Z 0:00 \_ [nova-novncproxy] <defunct>- w/ A. c* T2 r4 a# G
之前对于僵尸进程的了解并不深,该如何处理。 X; j5 }3 j' {' e6 C+ T/ \0 x, Y
! ?) G0 H* _# X定义
& R# }4 R2 W: O9 k7 `
2 w6 Z& f/ N* a+ jIn UNIX System terminology, a process that has terminated,but whose parent has not yet waited for it, is called a zombie.. ~* T: c+ M' I1 Y3 ^/ n' b
3 E+ t% G: ^& n2 d. X/ M
在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程. 在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用 waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程。
4 u1 |) {) k8 W! g) [4 j
7 c9 S7 X3 \0 J( x4 [如何查看linux系统上的僵尸进程,如何统计有多少僵尸进程?' ?: D- [, K& k; l' F+ _4 ?2 t
1 I1 F; e0 f8 j% |#ps -ef | grep defunct/ {" N6 ?- R9 N5 h. W
' Y6 ]) o/ Q1 ^- N+ E3 x0 x5 `
或者查找状态为Z的进程,Z就是代表zombie process,僵尸进程的意思。2 h( U+ v8 I- G/ b& F0 B
: Q0 r. e9 b4 E. H
另外使用top命令查看时有一栏为S,如果状态为Z说明它就是僵尸进程。* ^& I2 A4 [0 j
U3 `$ H& e3 M1 n5 h: x. kTasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie. g. c9 p. r9 f. t2 b5 f6 H5 }8 ^0 y
{) P \8 }7 c% O
top命令中也统计了僵尸进程。或者使用下面的命令:! k, J2 p! U$ j
4 j" S& L* G- C
ps -ef | grep defunct | grep -v grep | wc -l3 u( W! r8 N/ a& {! D( j: o8 \! s
( o) C% ?: S8 ]6 x
如何杀死僵尸进程呢?
6 u1 h; c/ B' d% g& ^5 O+ e一般僵尸进程很难直接kill掉,不过您可以kill僵尸爸爸。父进程死后,僵尸进程成为”孤儿进程”,过继给1号进程init,init始终会负责清理僵尸进程.它产生的所有僵尸进程也跟着消失。
/ d' z! }. Z& m' z- B1 V
: r* H/ {+ |$ q& [ps -e -o ppid,stat | grep Z | cut -d” ” -f2 | xargs kill -9
! |; k; x6 a* F7 z6 H3 q. `, {
& p1 C, P% G3 J或2 J+ x3 e" ^5 U# [ f" L
; e6 e6 L; Y9 s+ A* i4 H
kill -HUP `ps -A -ostat,ppid | grep -e ’^[Zz]‘ | awk ’{print $2}’`
" g- \7 Q0 j7 d$ S, ?9 K, |6 Z
2 m4 G! w0 u! X( Q( a) ]1 ~4 ~当然您可以自己编写更好的shell脚本,欢迎与大家分享。$ o$ v# k7 s% Q) m
$ V! F% g1 c5 P( E
我将nova-novncproxy stop后再start,僵尸进程即消失,问题解决。
' b5 l2 {# J5 f. t3 z0 o7 O) v0 t! k' s
另外子进程死后,会发送SIGCHLD信号给父进程,父进程收到此信号后,执行waitpid()函数为子进程收尸。就是基于这样的原理:就算父进程没有调用wait,内核也会向它发送SIGCHLD消息,而此时,尽管对它的默认处理是忽略,如果想响应这个消息,可以设置一个处理函数。* z6 t6 b! b/ a5 ?: U. w7 K
0 G9 ] K5 ?6 p V; \
如何避免僵尸进程呢?
, v' o; r+ ]4 S8 K, B2 O处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下 可以简单地将 SIGCHLD信号的操作设为SIG_IGN。
( [+ A& D2 O# S" S7 N+ Fsignal(SIGCHLD,SIG_IGN);0 g- y' R6 l6 a( R$ B0 L4 _
这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程
4 O i. A) R# K# D6 V. n9 C5 \. z4 \' Z: R" z& g3 u
或者2 C$ R4 T. T5 S/ f! C& I
, k) ?2 m7 C4 U8 i& A用两次fork(),而且使紧跟的子进程直接退出,是的孙子进程成为孤儿进程,从而init进程将负责清除这个孤儿进程。 |
|