如何杀掉由NFS造成Uninterruptible的进程

来源:互联网 发布:52mac vip账号 编辑:程序博客网 时间:2024/05/21 14:15

一台机器上mount了一很多nfs的分区,但是其中一个nfs server挂了(硬件问题一时启动不起来)。结果几个df进程就跟着挂起了,并且用kill -9也杀不掉。当时的进程状态是:

[jianingy(0)@xxxxxx ~]$ ps ax -o pid,wchan,s,command | grep df$  3505 rpc_ex D df  3844 rpc_ex D df  4162 rpc_ex D df    [jianingy(0)@xxxxxx ~]$ pstree  init─┬─acpid       ├─agetty       ├─atd       ├─crond       ├─dbus-daemon-1       ├─3*[df]  ...  

所有df都wait在了rpc_execute。进程都在uninterruptible sleep(即ps的D状态),因此不会处理任何信号。经过广泛的搜索,发现rpc_execute所需数据由rpciod提供。因此只要killall -KILL rpciod就可以终止rpc_execute调用, 而rpciod在被杀掉后会自己重启过来。

另外出现这种情况大多因为使用默认方式mount了nfs, 这种情况下连接失败时nfs客户端会不停尝试连接服务器。在mount时使用intr选项可以避免这类问题的出现。下面贴一段nfs mount option的说明

soft If an NFS file operation has a major timeout then report an I/O error to the calling program. The default is to continue retrying NFS file operations indefinitely.

hard If an NFS file operation has a major timeout then report “server not responding” on the console and continue retrying indefinitely. This is the default.

intr If an NFS file operation has a major timeout and it is hard mounted, then allow signals to interupt the file operation and cause it to return EINTR to the calling program. The default is to not allow file operations to be interrupted.


消灭状态为D或Z的进程(zz)

长期生活在 Linux 环境里,渐渐地就有一种环保意识油然而生。比如,我们会在
登录提示里写上“悟空,我跟你说过叫你不要乱扔东西,乱扔东西是不对的。哎呀我话没说
完你怎么把棍子扔掉了?月光宝盒是宝物,乱扔它会污染环境,要是砸到小朋友怎么办?就
算砸不到小朋友,砸到了花花草草也不好嘛…”;在用户缺省目录里放一个题为 “自觉保                                        
护环境 请勿堆放垃圾”的空文件,并用 chattr +i 设为不可修改;看到垃圾文件就立即扫
入 /tmp 目录,然后发广播通知垃圾制造者自己去 /tmp 认领,且警告其下不为例…我们深
知,系统环境的整洁有利于系统管理员保持良好的心情、清晰的思路和稳定的工作状态。

        有一类垃圾却并非这么容易打扫,那就是我们常见的状态为 D(Uninterruptible
sleep),以及状态为 Z(Zombie) 的垃圾进程。这些垃圾进程要么是求而不得,像怨妇一般
等待资源(D),要么是僵而不死,像冤魂一样等待超度(Z),它们在 CPU run_queue 里滞留
不去,把 Load Average 弄的老高老高,没看过我前一篇blog的国际友人还以为这儿民怨沸
腾又出了什么大事呢。怎么办?开枪!kill -9!看你们走是不走。但这两种垃圾进程偏偏
是刀枪不入的,不管换哪种枪法都杀不掉它们。无奈,只好reboot,像剿灭禽流感那样不分
青红皂白地一律扑杀!

        悟空,我们所运维的可是24*7全天候对外部客户服务的系统,怎么能动不动就
reboot ?我们的考核指标可是4个9(99.99%,全年计划外当机时间不得超过52分钟34秒),
又不是4个8,你稍微遇到点事就reboot,还要不要可用性了?再说,现在社会都开始奔和谐
去了,我们对于 D 和 Z 这两种垃圾进程,也该尽可能采取慈悲手段,能解决其困难的,就
创造条件,解决其实际困难,能消除其冤结的,就诵经烧纸,消除其前世冤结,具体问题应
具体分析具体解决,滥杀无辜只会导致冤冤相报因果循环…$^#$%#%^@#

        贫僧还是回来说正题。怨妇 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 时再次发生等待资源,导致系统重启过程挂起。冤魂 Z 之所以杀不死,是因为
它已经死了,否则怎么叫 Zombie(僵尸)呢?冤魂不散,自然是生前有结未解之故。在
UNIX/Linux中,每个进程都有一个父进程,进程号叫PID(Process ID),相应地,父进程号
就叫PPID(Parent PID)。当进程死亡时,它会自动关闭已打开的文件,舍弃已占用的内存、
交换空间等等系统资源,然后向其父进程返回一个退出状态值,报告死讯。如果程

        悟空,我们所运维的可是24*7全天候对外部客户服务的系统,怎么能动不动就
reboot ?我们的考核指标可是4个9(99.99%,全年计划外当机时间不得超过52分钟34秒),
又不是4个8,你稍微遇到点事就reboot,还要不要可用性了?再说,现在社会都开始奔和谐
去了,我们对于 D 和 Z 这两种垃圾进程,也该尽可能采取慈悲手段,能解决其困难的,就
创造条件,解决其实际困难,能消除其冤结的,就诵经烧纸,消除其前世冤结,具体问题应
具体分析具体解决,滥杀无辜只会导致冤冤相报因果循环…$^#$%#%^@#

        贫僧还是回来说正题。怨妇 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 时再次发生等待资源,导致系统重启过程挂起。冤魂 Z 之所以杀不死,是因为
它已经死了,否则怎么叫 Zombie(僵尸)呢?冤魂不散,自然是生前有结未解之故。在
UNIX/Linux中,每个进程都有一个父进程,进程号叫PID(Process ID),相应地,父进程号
就叫PPID(Parent PID)。当进程死亡时,它会自动关闭已打开的文件,舍弃已占用的内存、
交换空间等等系统资源,然后向其父进程返回一个退出状态值,报告死讯。如果程序有
bug,就会在这最后一步出问题。儿子说我死了,老子却没听见,没有及时收棺入殓,儿子
便成了僵尸。在UNIX/Linux中消灭僵尸的手段比较残忍,执行 ps axjf 找出僵尸进程的父
进程号(PPID,第一列),先杀其父,然后再由进程天子 init(其PID为1,PPID为0)来一起收
拾父子僵尸,超度亡魂,往生极乐。注意,子进程变成僵尸只是碍眼而已,并不碍事,如果
僵尸的父进程当前有要务在身,则千万不可贸然杀之。

        关于ZOMBIE进程:
        这些进程已经死亡,但没有释放系统资源,包括内存和一些一些系统表等,如果这
样的进程很多,会引发系统问题。用ps -el看出的进程状态如果是Z,就是僵尸进程。ps
-ef|grep defunc可以找出僵尸进程。

        有些ZOMBIE进程时用kill -9也不能杀死,而且消耗了很多系统资源不能释放,如
果系统在shutdown时发出信息:some process wouldn’t die。 这就意味这有些进程不能被
reboot发出的kill -9杀掉,这些很可能就是僵尸进程。

        可以用ps 的 -l 选项,得到更详细的进程信息:

        F(Flag):一系列数字的和,表示进程的当前状态。这些数字的含义为:
        00:若单独显示,表示此进程已被终止。
        01:进程是核心进程的一部分,常驻于系统主存。如:pdflush 等。
        02:Parent is tracing process。
        04:Tracing parent’s signal has stopped the process; the parent is
waiting(ptrace(S))。
        10:进程在优先级低于或等于25时,进入休眠状态,而且不能用信号唤醒,例如在
等待一个 inode 被创建时。
        20:进程被装入主存(primary memory)
        40:进程被锁在主存,在事务完成前不能被置换

        S(state of the process)
        O:进程正在处理器运行
        S:休眠状态(sleeping)
        R:等待运行(runable)
        I:空闲状态(idle)
        Z:僵尸状态(zombie)
        T:跟踪状态(Traced)
        B:进程正在等待更多的内存页
        C(cpu usage):cpu利用率的估算值

        清除ZOMBIE(僵尸)进程可以使用如下方法:
        1> kill -18 PPID (PPID是其父进程)
        这个信号是告诉父进程,该子进程已经死亡了,请收回分配给他的资源。

        2>如果不行则看能否终止其父进程(如果其父进程不需要的话)。先看其父进程又无
其他子进程,如果有,可能需要先kill其他子进程,也就是兄弟进程。方法是:
        kill -15 PID1 PID2(PID1,PID2是僵尸进程的父进程的其它子进程)。
        然后再kill父进程:kill -15 PPID

        这样僵尸进程就 *可能* 被完全杀掉了。

链接:http://baikgd.blog.163.com/blog/static/354024952011931104328509/

http://www.yangsheep.net/wuyang/wordpress/?p=110