1. Linux进程状态
Running(R
):运行或将要运行
Interruptible(S
):被阻断而等待一个事件,可能会被一个信号**
Uninterruptible(D
):被阻断而等待一个事件,不会被信号**
Stopped(T
):由于任务的控制或者外部的追踪而被终止,比如:strace
Zombie(Z
):僵死,但是它的父进程尚未调用wait函数.
Deal(X
):这个永远看不见
2. 睡眠状态disk sleep
Linux进程有两种睡眠状态,一种interruptible sleep
,处在这种睡眠状态的进程是可以通过给它发信号来唤醒的,也是可以kill的,进程状态如下
#cat /proc/[pid]/status
Name: sysmgt
State: S (sleeping)
另外一种睡眠状态是uninterruptible sleep
,处在这种状态的进程不接受外来的任何信号,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是”kill”, “kill -9″还是”kill -15″,因为它们压根儿就不受这些信号的支配。
#cat /proc/[pid]/status
Name: sysmgt
State: D (disk sleeping)
进程为什么会被置于uninterruptible sleep
状态呢?处于uninterruptible sleep
状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被 ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如挂载的远程文件系统已经不可访问了,我这里遇到的问题就是由互斥锁引起的,比如说我开了8个进程同时访问一个io,访问的时候势必会加锁来保护资源,那么,当一个进程正在访问的时候,其他进程如果在等待锁,那么就会进入disk sleep,当你执行kill,它不会立即响应,当锁满足条件的时候才可能响应信号。https://blog.csdn.net/davion_zhang/article/details/48268319
3. 场景重现
今天遇到云主机系统盘磁盘占用率100%,(因之前运维部署失误导致现存问题),主机有挂载nfs存储,将系统盘大文件拷贝到nfs中使用mv或者cp命令直接变成D状态进程。
[root@iZ25l1lr9hoZ ~]# ps -ef | grep mv
root 1261 32321 0 15:11 pts/8 00:00:00 grep mv
root 31838 1 0 14:47 ? 00:00:00 mv -i ./logdb20210407110846705 /filebackup/logdbcopy-backup
[root@iZ25l1lr9hoZ ~]# kill -9 31838 ==>kill -9 杀不掉进程
[root@iZ25l1lr9hoZ ~]# ps -ef | grep mv
root 1261 32321 0 15:11 pts/8 00:00:00 grep mv
root 31838 1 0 14:47 ? 00:00:00 mv -i ./logdb20210407110846705 /filebackup/logdbcopy-backup
[root@iZ25l1lr9hoZ ~]# cat /proc/31838/status
Name: mv
State: D (disk sleep)
Tgid: 31838
Pid: 31838
PPid: 1
...
4. 解决方案
D状态(disk sleep)进程用kill -9命令是不管用的,最简单的方法就是reboot
重启, 除此还可以修改内核,将其进程状态转化为别的状态,然后kill掉,非必要不建议修改内核影响不确定。