Linux CPU 占用过高怎么排查?top、ps、pidstat

1. 前言

Linux 服务器 CPU 占用过高,是线上排障中非常常见的问题。
常见现象包括:

  • 接口响应变慢;
  • SSH 登录卡顿;
  • 服务线程堆积;
  • 负载 Load Average 升高;
  • 风扇转速变高;
  • 进程占用 CPU 长时间不下降。

排查 CPU 问题,不能只看一个 top
更合理的方式是结合:


top
ps
pidstat
uptime
mpstat
perf
应用日志

本文重点围绕 toppspidstat 展开,讲清楚 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 核心

pidstattop 更适合连续观察趋势。


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 高

topus 高。

常见原因:

  • 业务计算量大;
  • 死循环;
  • 大量 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

除非已经确认是异常进程。

更稳妥:

  1. 先记录现场;
  2. 保存日志;
  3. 查看进程命令;
  4. 查看线程;
  5. 必要时 dump;
  6. 再考虑重启或 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 等待还是中断上。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐