
我在一次香港服务器例行维护过程中,我遭遇了一个棘手的问题:某个关键业务进程kill不掉,即使用了 kill -9,也毫无反应。今天我就以这次事故为例,和你聊聊如何深度诊断和修复Linux服务器中无法终止的进程,尤其是在我们这种对可靠性要求极高的香港托管环境中。
一、故障背景及硬件环境
这台服务器托管于香港将军澳的数据中心,我们使用的是一台戴尔 PowerEdge R750xa,配置如下:
- CPU: Intel Xeon Gold 6338 (32核64线程)
- 内存: 512GB DDR4 ECC
- 存储: 三块2TB NVMe SSD (RAID 5)
- 操作系统: CentOS 7.9, 内核版本:3.10.0-1160.95.1.el7.x86_64
主要运行容器化服务(Docker),服务包括Redis、MySQL、Nginx和一套Node.js后端API
当时的问题出现在某个Node.js服务的容器内进程,容器ID为 b6c4e987cebf,PID为 29456,进程状态一直为 D(Uninterruptible Sleep),kill无效,甚至导致整个容器无法重启。
二、尝试常规方法无效的情况
首先我尝试了所有标准操作:
kill -9 29456 # 无效
docker stop b6c4e987cebf # 卡住
ps aux | grep 29456 # 状态为 'D'
什么是状态 “D”?
在Linux中,“D”状态代表“不可中断的睡眠”,通常是等待I/O操作完成,比如磁盘、网络等。如果一个进程长时间处于该状态,就说明它可能被卡死在内核态的某个驱动或系统调用中。
三、问题定位思路
1. 查看内核调用栈
我用了 cat /proc/29456/stack 来查看内核调用栈:
cat /proc/29456/stack
输出如下(部分内容):
[<0>] io_schedule+0x16/0x40
[<0>] wait_on_page_bit+0x11c/0x1b0
[<0>] filemap_fault+0x6e1/0xb30
[<0>] __do_fault+0x3f/0x100
很明显,这个进程在等待磁盘I/O,具体是文件系统层的 filemap_fault。
2. 检查磁盘I/O状态
接着我用了 iotop 和 iostat 观察磁盘是否有异常:
iotop -ao
iostat -x 1 5
结果发现 /dev/nvme0n1 的 await 值高达 540ms+,说明有明显的I/O堵塞,怀疑是容器写入文件时卡死。
3. 分析容器文件系统挂载
查看 Docker 的容器挂载方式:
docker inspect b6c4e987cebf | grep Mnt
发现这个容器的数据卷是挂载到 /var/lib/docker/overlay2/,而底层使用的是 overlay2 文件系统,直接绑定在 /dev/nvme0n1 上。
进一步分析:
dmesg | grep nvme
输出出现了这样的警告:
nvme nvme0: I/O 244 QID 0 timeout, aborting
很明显是NVMe磁盘硬件出现响应超时。
四、实战解决方案
既然 kill -9 都无法终止,我们就要转而从I/O层解决问题。
方案 1:使用 fuser 和 lsof 找到被占用的文件
fuser -m /var/lib/docker/overlay2/
lsof | grep 29456
确认是某个日志文件 /var/lib/docker/overlay2/…/merged/var/log/app.log 被卡住,尝试重定向或清空:
> /var/lib/docker/overlay2/.../merged/var/log/app.log
未果,因为进程根本没有响应。
方案 2:强制卸载对应挂载点(失败)
尝试:
umount -l /var/lib/docker/overlay2/...
依旧无效,因为文件系统处于繁忙状态。
方案 3:隔离I/O通道 + 热插拔重置 NVMe
这是关键一步,我们通过 Dell iDRAC 9 远程控制平台,执行了以下步骤:
- 使用 echo 1 > /sys/block/nvme0n1/device/remove 命令从系统中卸载设备(慎用)
- 热插拔 NVMe(戴尔服务器支持在线更换)
- 使用 echo “- – -” > /sys/class/scsi_host/host0/scan 重新扫描设备
- 文件系统恢复正常,进程立即退出
注意:这个过程需要配合 iDRAC 管理平台远程操作,必须确认应用已经容灾或暂停服务,否则会导致数据丢失。
五、后续优化与总结
1. 增加磁盘健康监控
我们在 Zabbix 中添加了以下指标监控:
- nvme smart-log
- iostat await > 200ms 警报
- Docker 容器挂载路径 I/O 响应时间
2. 优化应用日志写入策略
将 Node.js 的日志输出改为使用 syslog + Fluentd 异步收集,避免直接写本地磁盘。
3. 为容器配置 I/O 限流
使用 –device-write-bps 为 Docker 容器设置写入带宽限制:
docker run --device-write-bps /dev/nvme0n1:10mb ...
遇到进程无法终止这个问题,很多人第一反应是“系统挂了”,但只要你深入内核和I/O机制,其实背后大多是“某个硬件或驱动没有响应”。香港这种高密度数据中心环境,对磁盘I/O的压力非常大,所以必须从硬件层+容器层双管齐下做好防护。











