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

本文探讨了Linux环境下如何处理状态为D(不可中断睡眠)和Z(僵尸进程)的进程问题,提供了详细的方法和步骤,旨在帮助运维人员在不重启系统的情况下解决此类进程挂起的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一台机器上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

<think>好的,我现在需要解释Linux进程状态。首先,我得回忆一下Linux中进程有哪些状态。我记得常见的可能有运行、就绪、阻塞之类的,但具体的术语可能不同。比如,可能包括运行状态、可中断睡眠、不可中断睡眠等等。我需要确认这些状态的具体名称和含义。 然后,可能需要查证每个状态对应的缩写,比如R代表运行,S代表睡眠等。还要考虑是否有其他状态,比如僵尸进程(Z)和停止状态(T)。有没有被终止的进程状态?或者僵死状态的不同情况? 接下来,要详细说明每个状态的具体情况。例如,运行状态(R)是进程正在CPU执行还是就绪等待调度?可中断睡眠(S)和不可中断睡眠(D)的区别是什么?什么时候进程会进入不可中断睡眠?比如,等待I/O操作完成时,特别是磁盘I/O,可能不可中断。 僵尸进程(Z)的形成原因是什么?当子进程终止但父进程尚未调用wait()时,会保留进程描述符,导致僵尸状态。停止状态(T)通常是由于信号(如SIGSTOP)暂停的进程,可以通过SIGCONT恢复。 可能还需要提到其他较少见的状态,比如跟踪状态(t),或者死亡状态(X)。不过X状态可能不会在常规工具中显示,因为进程已经终止,资源被释放。 需要确保解释清晰,每个状态的定义、触发条件,以及如何查看这些状态。例如,使用ps命令时,STAT列显示的状态代码。可能还要举例说明,比如使用ps aux命令查看进程状态。 另外,用户可能想知道如何处理僵尸进程或停止的进程。比如,死父进程来清除僵尸进程,或者发送CONT信号恢复停止的进程。这部分是否需要包含?可能简要提及解决方案。 要避免错误,比如混淆可中断和不可中断睡眠的区别。不可中断睡眠通常发生在进程等待硬件条件,不能被信号打断,而可中断的可以被信号唤醒。 总结结构应该是先列出所有状态,每个状态用简短的标题,然后详细说明。可能需要使用列表或表格来组织信息,但由于用户要求用markdown,可以适当使用列表和代码块示例。 最后,检查是否有遗漏的状态,确保覆盖主要的进程状态,并解释清楚每个状态的意义和常见场景。</think>```markdown # Linux进程状态详解 ## 一、基础状态类型 Linux进程状态通过`ps`命令的STAT列显示,使用单个字母表示: | 状态符 | 名称 | 说明 | |--------|-----------------------|----------------------------------------------------------------------| | R | Running | 正在运行或就绪状态(等待CPU调度) | | S | Interruptible Sleep | 可中断睡眠(等待事件完成,可被信号唤醒) | | D | Uninterruptible Sleep | 不可中断睡眠(通常等待硬件I/O,不响应信号) | | Z | Zombie | 僵尸进程(已终止但未被父进程回收) | | T | Stopped | 进程被信号暂停(SIGSTOP)或正在被调试器跟踪 | | t | Tracing stop | 进程在调试期间被跟踪暂停 | | X | Dead | 完全死亡状态(仅出现在某些内核版本中,通常不可见) | ## 二、详细状态说明 ### 1. 运行状态 (R) ```bash # 示例进程 $ ps aux | grep '\[kworker\]' root 50 0.0 0.0 0 0 ? R 12:00 0:01 [kworker/0:3] ``` - 包含两种子状态: - **实际运行**:正在使用CPU时间片 - **就绪状态**:等待CPU调度队列中 ### 2. 可中断睡眠 (S) ```bash # 等待用户输入的进程 $ sleep 60 & [1] 12345 $ ps -p 12345 -o pid,stat PID STAT 12345 S ``` - 常见场景: - 等待终端输入 - 等待socket连接 - 可被信号中断唤醒 ### 3. 不可中断睡眠 (D) ```bash # 常见于NFS操作或硬件操作 $ ps aux | grep 'jbd2/sda' root 348 0.0 0.0 0 0 ? D 12:00 0:00 [jbd2/sda1-8] ``` - 典型场景: - 同步磁盘I/O操作 - NFS文件系统访问 - 硬件设备交互 - **危险状态**:无法通过`kill -9`终止 ### 4. 僵尸进程 (Z) ```bash # 创建僵尸进程示例 $ python -c 'import os; os.fork() or os._exit(0)' & $ ps aux | grep 'defunct' user 12456 0.0 0.0 0 0 Z 12:00 0:00 [python] <defunct> ``` - 形成原因: - 子进程已终止 - 父进程未调用`wait()`/`waitpid()` - 处理方式: - 终止父进程(自动回收僵尸) - 手动发送`SIGCHLD`信号给父进程 ### 5. 停止状态 (T) ```bash # 暂停进程示例 $ kill -SIGSTOP 12345 $ ps -p 12345 -o pid,stat PID STAT 12345 T ``` - 触发方式: - `Ctrl+Z`发送SIGTSTP - `kill -SIGSTOP <pid>` - 恢复方式: - `fg`命令或`kill -SIGCONT <pid>` ## 三、特殊状态组合 ### 1. 多线程进程 ```bash # 多线程进程显示 $ ps -eLf | grep 'java' UID PID PPID LWP C NLWP STAT STIME TTY TIME CMD user 6789 6788 6789 5 32 Sl 12:00 ? 00:01:23 java -server ``` - **Sl**:多线程进程(主线程睡眠) - **多字母状态码**: - `<`:高优先级 - `N`:低优先级 - `L`:有锁定的内存页 - `s`:会话首进程 ### 2. 前台/后台状态 | 符号 | 说明 | |------|---------------------| | + | 进程在前台进程组 | | l | 多线程(使用CLONE_THREAD) | | < | 高优先级 | ## 四、状态查看命令 ### 1. 经典查看方式 ```bash $ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 225364 9428 ? Ss Jul31 0:32 /sbin/init ``` ### 2. 显示线程状态 ```bash $ ps -eLf $ top -H # 线程视图模式 ``` ### 3. 实时监控 ```bash $ top -d 1 # 每秒刷新 ``` **关键字段说明**: - PR:内核调度优先级 - NI:用户设置的nice值 - S:进程状态(单字母代码) > **注意**:当进程状态显示`D`超过120秒时,可能触发内核的hung task检测机制 ```bash # 查看hung task日志 $ dmesg | grep -i 'hung task' ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值