Linux 服务器 CPU 飙高:用 top、ps、perf 与 /proc 定位的完整流程
服务器 CPU 一下子冲到 90% 以上,先不要急着重启,也不要只看某一个进程的瞬间值。CPU 高只是一个结果,真正要分清的是:到底是谁在消耗、消耗在哪一类时间上、是不是可以安全地停下来。下面按先定性、再定位、最后验证的顺序走一遍。
一、先看整体,区分四种高
打开 top,重点看第三行和任务区。
top
us 高,说明用户态程序在算、在循环、在做业务逻辑;sy 高,说明系统态开销大,可能是大量系统调用、锁竞争、频繁创建销毁线程或进程、网络收发包过多;wa 高,表面看是 CPU 空闲却在等磁盘,这时瓶颈往往在磁盘而不是计算本身;hi 与 si 高,则要怀疑中断和软中断,常见于网卡收包量突增或驱动异常。
同时看 load average。单核机器 load 长期大于 1、多核机器 load 长期大于核数,才算持续承压;瞬时冲高而很快回落,先看是不是定时任务、备份、日志轮转或批量作业在跑。
二、用 ps 找到可疑进程
top 只能看前几名,排序结果也受刷新影响。用 ps 做一次快照:
ps aux --sort=-%cpu | head -20
ps -eo pid,ppid,%cpu,%mem,etime,cmd --sort=-%cpu | head -20
记下 PID、父进程、启动时间和累计 CPU 时间。一个刚启动就占满 CPU 的进程,和一个跑了很久、CPU 时间缓慢累积的进程,排查方向完全不同。前者看启动参数和配置,后者看是不是进入了死循环或低效循环。
如果怀疑某个服务内部的线程,先看线程级占用:
top -H -p <PID>
ps -T -p <PID> -o pid,tid,pcpu,psr,stat,comm
线程级信息很关键,很多服务主进程不高,但某一个工作线程长期占满一个核。
三、用 pidstat 和 /proc 做时间维度的确认
只看一瞬间容易误判。用 pidstat 连续采样,确认占用是否持续:
pidstat -u -p <PID> 2 5
pidstat -u -t -p <PID> 2 5
再看进程状态文件,确认它到底在做什么:
cat /proc/<PID>/status
cat /proc/<PID>/stat
ls -l /proc/<PID>/task
cat /proc/<PID>/task/<TID>/status
status 里的 State、Threads、voluntary_ctxt_switches 和 nonvoluntary_ctxt_switches 值得对照看。频繁自愿切换多见于等待锁或等待 IO,频繁非自愿切换则可能是在抢 CPU。线程目录可以帮你把 top 里看到的高占用线程,和具体的线程号对应起来。
四、用 perf 看热点函数,而不是猜代码
进程找到了,接下来要回答:它的 CPU 花在哪个函数上。先用 perf top 做实时观察:
perf top -p <PID>
如果需要留档分析,再采样后生成报告:
perf record -p <PID> -g -- sleep 30
perf report
注意三点:采样时间不要太短,30 秒左右更能反映真实热点;生产环境先确认 perf 是否可用、是否需要相应权限;结果要结合业务代码看,热点函数是循环、正则、序列化、加解密还是锁等待,处理方法完全不同。热点在业务代码里,修代码或限流;热点在内核函数里,先看系统调用和中断情况。
五、必要时用 strace 做简要定位
perf 告诉你函数,strace 告诉你它在和系统打什么交道:
strace -f -tt -p <PID> -o /tmp/strace.log
只采短时间,采样完立刻停。重点看是否在反复调用同一个系统调用、是否大量返回错误、是否有极短间隔的读写或 futex 等待。strace 本身有开销,不要长时间挂在高负载进程上,也不要在采样期间做其他重操作。
六、按类型收尾,避免误杀
用户态死循环:先保留现场,记录 PID、线程号、perf 采样和日志片段,再按变更流程重启或回滚相关服务;系统态偏高:检查最近的配置变更、连接数、线程数和定时任务,必要时先限流再排查;iowait 偏高:先查磁盘、文件系统和慢查询,不要只加 CPU;中断偏高:检查网卡流量、队列和驱动版本,必要时调整中断亲和性。
最后形成一个固定习惯:先 top 定性,再 ps 定进程,再用线程和 pidstat 确认持续性,再用 perf 定函数,最后用 /proc 和 strace 补齐证据。这样每次排查都有据可查,也不会因为一次瞬时冲高就误判故障。
- 点赞
- 收藏
- 关注作者
评论(0)