Linux CPU占用过高的原因与排查指南
1. 前言
Linux 服务器 CPU 占用过高,是线上排障中非常常见的问题。
常见现象包括:
- 接口响应变慢;
- SSH 登录卡顿;
- 服务线程堆积;
- 负载 Load Average 升高;
- 风扇转速变高;
- 进程占用 CPU 长时间不下降。
排查 CPU 问题,不能只看一个 top。
更合理的方式是结合:
top ps pidstat uptime mpstat perf 应用日志
本文重点围绕 top、ps、pidstat 展开,讲清楚 Linux CPU 占用过高时怎么定位到具体进程、线程和可能原因。
2. CPU 占用高可能是什么原因
CPU 高并不一定是坏事。
如果服务器正在正常处理大量请求,CPU 高可能是正常负载。
但如果 CPU 持续高位,就要重点排查。
常见原因:
| 类型 | 说明 |
|---|---|
| 业务请求量突增 | 流量变大,服务正常忙 |
| 死循环 | 某段代码一直空转 |
| 线程池打满 | 大量线程争抢 CPU |
| GC 频繁 | Java 程序频繁垃圾回收 |
| 正则或加密计算过重 | CPU 密集型任务 |
| 日志疯狂打印 | 大量字符串拼接和 IO |
| 异常进程 | 挖矿、木马、未知脚本 |
| 系统中断高 | 网卡、磁盘、驱动异常 |
所以排查时要先判断:
是哪个进程高? 是用户态 CPU 高,还是系统态 CPU 高? 是单线程高,还是多线程高? CPU 高是否和业务流量一致?
3. top:第一时间看整体情况
执行:
top
重点看顶部几行:
%Cpu(s): 85.0 us, 10.0 sy, 0.0 ni, 3.0 id, 1.0 wa, 0.0 hi, 1.0 si, 0.0 st
字段说明:
| 字段 | 含义 |
|---|---|
us | 用户态 CPU,业务程序代码消耗 |
sy | 系统态 CPU,内核调用消耗 |
id | 空闲 CPU |
wa | 等待 IO |
hi | 硬中断 |
si | 软中断 |
st | 虚拟化环境中被宿主机偷走的 CPU |
判断思路:
| 现象 | 可能方向 |
|---|---|
us 高 | 应用程序计算多、死循环、GC、业务压力大 |
sy 高 | 系统调用多、网络/文件操作频繁 |
wa 高 | 磁盘 IO 慢,不一定是 CPU 真忙 |
hi/si 高 | 网络包、中断、驱动相关问题 |
st 高 | 云主机宿主机资源争抢 |
4. top 中按 CPU 排序
进入 top 后按:
P
可以按 CPU 占用排序。
常见字段:
| 字段 | 说明 |
|---|---|
PID | 进程 ID |
USER | 进程用户 |
%CPU | CPU 占用 |
%MEM | 内存占用 |
TIME+ | 累计 CPU 时间 |
COMMAND | 命令名 |
如果某个进程长期排第一,基本就是重点对象。
查看某个进程详细信息:
ps -fp PID
例如:
ps -fp 12345
5. ps:快速找 CPU 最高的进程
查看 CPU 占用最高的前 10 个进程:
ps aux --sort=-%cpu | head
输出示例:
USER PID %CPU %MEM COMMAND app 1234 180 20.1 java -jar app.jar root 2345 60 1.2 nginx
说明:
%CPU可能超过 100;- 多核 CPU 下,一个进程多线程可以占用超过 100%。
查看指定进程:
ps -p 1234 -o pid,ppid,user,%cpu,%mem,etime,cmd
字段说明:
| 字段 | 含义 |
|---|---|
pid | 进程 ID |
ppid | 父进程 ID |
%cpu | CPU 占用 |
%mem | 内存占用 |
etime | 运行时长 |
cmd | 启动命令 |
6. pidstat:持续观察进程 CPU
pidstat 来自 sysstat 工具包。
安装:
Ubuntu / Debian:
sudo apt install sysstat -y
CentOS / RHEL:
sudo yum install sysstat -y
查看所有进程 CPU,每 1 秒一次:
pidstat 1
查看指定进程:
pidstat -p 1234 1
输出示例:
UID PID %usr %system %guest %wait %CPU CPU Command app 1234 80.0 10.0 0.0 0.0 90.0 1 java
字段说明:
| 字段 | 含义 |
|---|---|
%usr | 用户态 CPU |
%system | 系统态 CPU |
%wait | 等待 CPU 调度 |
%CPU | 总 CPU 占用 |
CPU | 当前运行在哪个 CPU 核心 |
pidstat 比 top 更适合连续观察趋势。
7. 定位到线程级别
有些进程内部有很多线程。
例如 Java、Nginx、MySQL 都可能是多线程或多进程模型。
查看某进程的线程 CPU:
top -H -p 1234
或者:
ps -mp 1234 -o THREAD,tid,time,%cpu
找到占用高的线程 TID 后,如果是 Java 程序,可以把 TID 转成十六进制:
printf "%x\n" 线程ID
例如:
printf "%x\n" 5678
然后用:
jstack 1234 | grep -A 30 十六进制线程ID
定位 Java 线程堆栈。
8. mpstat:看每个 CPU 核心
如果怀疑单核打满,可以用:
mpstat -P ALL 1
如果某一个 CPU 核心长期 100%,可能是:
- 单线程程序跑满;
- 中断集中在某个核心;
- 线程绑定 CPU;
- 某个热点线程异常。
9. CPU 高的实战排查流程
9.1 看整体 CPU
top
重点看:
us sy wa hi si st
9.2 找最高进程
ps aux --sort=-%cpu | head
9.3 持续观察
pidstat -p PID 1
9.4 看线程
top -H -p PID
9.5 查日志和应用状态
journalctl -u 服务名 -n 100 tail -f app.log
9.6 如果是 Java
jstack PID jstat -gcutil PID 1000
看是否频繁 GC 或线程死循环。
10. 常见场景判断
10.1 用户态 CPU 高
top 中 us 高。
常见原因:
- 业务计算量大;
- 死循环;
- 大量 JSON 序列化;
- 加密解密;
- 正则匹配;
- Java GC;
- 大量请求。
处理思路:
找进程 找线程 看代码堆栈 看接口流量 看日志
10.2 系统态 CPU 高
sy 高。
常见原因:
- 大量系统调用;
- 网络连接频繁创建关闭;
- 文件 IO 很频繁;
- 容器或内核网络开销;
- 进程频繁 fork。
可以结合:
strace -p PID
观察系统调用。
线上使用 strace 要谨慎,避免影响进程。
10.3 iowait 高
wa 高不代表 CPU 真忙。
它通常表示 CPU 在等磁盘 IO。
继续排查:
iostat -x 1 iotop
如果磁盘很忙,要去看 IO 问题,而不是只盯 CPU。
11. 不要一上来 kill -9
发现 CPU 高后,不建议直接:
kill -9 PID
除非已经确认是异常进程。
更稳妥:
- 先记录现场;
- 保存日志;
- 查看进程命令;
- 查看线程;
- 必要时 dump;
- 再考虑重启或 kill。
Java 程序可以先:
jstack PID > jstack.txt jmap -histo PID > histo.txt
然后再处理。
12. 小结
CPU 高排查核心命令:
top ps aux --sort=-%cpu | head pidstat -p PID 1 top -H -p PID mpstat -P ALL 1
排查思路:
先看整体 CPU 类型 ↓ 找出高 CPU 进程 ↓ 持续观察进程趋势 ↓ 定位到线程 ↓ 结合应用日志和代码堆栈 ↓ 判断是流量、死循环、GC、IO 还是异常进程
CPU 排查最重要的是不要只看表面占用率,而要判断 CPU 时间到底消耗在用户态、系统态、IO 等待还是中断上。
以上就是Linux CPU占用过高的原因与排查指南的详细内容,更多关于Linux CPU占用过高排查的资料请关注脚本之家其它相关文章!


最新评论