CentOS 上出现大量 sleeping(睡眠)进程怎么诊断?
sleeping(S 态)多数是正常的"等事件"状态;值得警惕的是 D 态(不可中断 IO 等待)和同一程序的大量 S 态堆积。诊断:ps/top 看分布、pstack/strace 看卡在哪、对照进程来源服务日志。
先定性:S 态(sleeping,可中断睡眠)本身是正常状态**——进程在等 IO 完成、等信号、等锁,闲着的 worker 都在睡。真正要警惕的是两种:①大量 D 态(不可中断睡眠,通常是磁盘/NFS IO 卡死);②同一程序的进程数异常膨胀(连接池泄漏、worker 堆积不回收)。**
第一步:看总量与分布
# 状态统计
ps -eo stat | sort | uniq -c | sort -rn
# 按程序名聚合 S/D 态
ps -eo stat,comm | grep -E '^S|^D' | sort | uniq -c | sort -rn | head
几百个 S 态来自同一服务(如 httpd、php-fpm、java 线程)→ 继续查;几十个分散在各系统进程 → 多半正常。
第二步:确认是不是"异常堆积"
正常参考:
- Apache/php-fpm:prefork/worker 池的空闲 worker 都在 S 态,数量≈配置上限属正常
- 数据库连接:每个连接一个线程/进程在 S 态等查询
- 异常信号:数量持续增长不回落、伴随内存上涨、伴随服务变慢
# 连续采样看趋势
for i in 1 2 3; do ps -eo stat,comm | grep ^S | wc -l; sleep 10; done
第三步:揪住具体进程看它在等什么
# 看进程在内核里卡在哪
cat /proc/<PID>/wchan; echo
cat /proc/<PID>/stack 2>/dev/null
# 看打开的文件/连接(句柄泄漏高发)
ls /proc/<PID>/fd | wc -l
lsof -p <PID> | head -30
# 动态跟踪系统调用
strace -p <PID> -c -f # Ctrl+C 出统计
D 态进程重点看:dmesg | tail(磁盘错误)、NFS 挂载是否僵死(mount | grep nfs)。
常见根因对照
| 现象 | 根因 |
|---|---|
| httpd/fpm 子进程打满且持续增长 | 慢请求堆积(慢 SQL/外部 API 卡住),worker 不释放 |
| 大量 D 态 + 高 load 低 CPU | 磁盘/NFS IO 故障,查 dmesg |
| java 应用 S 态线程暴涨 | 线程池/连接池泄漏,jstack 分析 |
| crond 残留大量 S 态 | cron 任务没退出(脚本 hang 住) |
观测云对照
进程级状态纳入监控。 DataKit 采集主机进程数(分状态)、单服务进程数与句柄数趋势;进程数持续爬升、D 态出现,监控器直接告警——比登录服务器手工 ps 快得多。
常见问题(FAQ)
Q:load average 高但 CPU 很闲?
A:load 统计包含 D 态进程——高 load 低 CPU 是 IO 卡死的典型特征,查磁盘与 NFS。
Q:僵尸进程(Z 态)和 S 态是一回事吗?
A:不是。Z 态是子进程退出后父进程没收尸,要处理父进程逻辑;S 态是正常等待。
Q:可以直接 kill 这些 sleeping 进程吗?
A:服务管理的 worker(httpd/fpm)kill 了会被自动拉起,无害但治标;先找到让它们堆积的慢请求源头。