找到元凶 -> 分析原因 -> 解决问题。

下面我将为你提供一个详细的、分步的排查和解决方案。
第一步:应急处理
如果服务器已经完全无响应,你可能需要通过其他方式登录,
- 物理控制台:直接在机房连接显示器和键盘。
- 带外管理:通过 iDRAC, iLO, IPMI 等远程管理卡。
- SSH 强制连接:有时 SSH 仍能连接,但会非常慢。
第二步:找到占用 CPU 100% 的元凶
一旦能登录到服务器,我们需要找到是哪个进程在作怪,主要使用 top 或 htop 命令。
使用 top 命令(经典方法)
- 输入
top并回车,你会看到一个实时更新的进程列表。 - 按
P键:确保进程列表是按照%CPU(CPU 使用率)从高到低排序的。 - 观察列表顶部的进程:找到
CPU%列最高的那个进程,这就是你的“元凶”。
top 命令输出关键信息解读:

top - 10:30:00 up 10 days, 2:15, 1 user, load average: 5.45, 5.12, 4.98
Tasks: 123 total, 2 running, 121 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.3% us, 0.2% sy, 0.0% ni, 0.5% id, 0.0% wa, 0.0% hi, 0.0% si, 0.0% st
KiB Mem : 16384000 total, 2048000 free, 8192000 used, 6144000 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 8192000 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 nginx 20 0 123456 78910 12345 R 99.9 0.5 10:30:01 httpd # <-- 这就是元凶!
67890 mysql 20 0 987654 543210 98765 S 0.1 3.2 120:45:67 mysqld
...
PID:进程 ID,这是最重要的信息,用于后续操作。%CPU:该进程的 CPU 使用率。COMMAND:进程名。
使用 htop 命令(更直观)
如果你的系统安装了 htop(yum install htop 或 apt install htop),它比 top 更好用。
- 输入
htop并回车。 - 默认就是按 CPU 使用率排序。
- 用鼠标或方向键选中占用 CPU 最高的进程,按
F9可以直接杀死它,非常方便。
第三步:深入分析元凶
找到 PID 和进程名后,你需要判断它为什么会占用如此高的 CPU。
场景1:可以立即杀死的进程
如果进程是一个临时性、非关键的任务,比如一个编译脚本、一个跑飞的 Python 脚本等,最直接的方法就是杀死它。
-
正常杀死:
kill <PID>
kill 12345 -
强制杀死(如果正常杀死无效):
kill -9 <PID>
kill -9 12345警告:kill -9是强制终止,进程无法做任何清理工作,可能会导致数据损坏或文件锁定,请谨慎使用,仅在必要时使用。
场景2:需要分析的顽固进程
如果进程是核心服务(如 nginx, httpd, mysqld, java 等),不能轻易杀死,你需要分析它到底在做什么。
步骤 1:查看进程启动命令和参数
# 使用 ps 命令 ps -ef | grep <PID> # 或者 ps -p <PID> -o pid,ppid,cmd,etime,lstart
这能告诉你这个进程是如何被启动的,它的完整命令行是什么。
步骤 2:查看进程正在执行的代码(最关键的一步)
使用 strace 或 perf 工具来跟踪进程的系统调用或行为。
-
使用
strace跟踪系统调用:strace可以告诉你进程在等待什么、在读写什么文件、在执行什么系统调用,这对于发现 I/O 瓶颈或异常行为非常有用。# -p 指定 PID, -f 跟踪子进程, -s 显示字符串长度, -o 输出到文件 strace -p <PID> -f -s 999 -o /tmp/strace.log
然后观察终端输出或
/tmp/strace.log文件,如果看到大量的read,write,open等调用,说明可能在进行大量 I/O,如果看到poll,select,epoll_wait,说明可能在等待网络或 I/O 事件。 -
使用
perf分析 CPU 性能(推荐)perf是 Linux 系统自带的强大性能分析工具,可以帮你定位到具体的函数代码。# 采样 30 秒,将结果存入 perf.data perf record -g -a -- sleep 30 # 分析结果 perf report
perf report会生成一个交互式报告,你可以展开调用栈,看到是哪个函数(甚至哪一行代码)消耗了最多的 CPU,这对于定位有问题的代码(如死循环、低效算法)是致命的。
步骤 3:查看进程的线程
一个高 CPU 占用是由其某个子线程引起的,而不是主进程。
-
使用
top查看线程: 在top界面,按H键,会切换到线程视图,你会看到很多/<进程名>的条目,这些就是线程,找到其中 CPU 占用最高的那个线程。 -
将线程 ID 转换为十六进制: 假设你找到了一个占用 CPU 很高的线程 ID 是
12346。printf "%x\n" 12346 # 假设输出结果是 3042
-
使用
jstack(针对 Java)或gdb分析线程栈-
对于 Java 进程:
# jstack 需要安装 JDK jstack <PID> > /tmp/jstack.log
然后用
grep搜索你刚才得到的十六进制线程 ID3042,就能看到该线程完整的调用栈,知道它在执行什么任务。 -
对于其他进程(如 C/C++): 使用
gdb:gdb -p <PID> # (gdb) info threads # 查看所有线程 # (gdb) thread <TID> # 切换到高 CPU 的线程 # (gdb) bt # 打印调用栈
-
第四步:常见原因与解决方案
通过以上分析,你通常会找到以下几种情况:
| 原因现象 | 可能原因 | 解决方案 |
|---|---|---|
某个 Web 服务进程 (httpd, nginx) |
某个 PHP/Python/Java 应用有死循环、正则表达式灾难、数据库慢查询。 | 使用 strace/perf 定位问题脚本。检查网站日志,找到是哪个 URL 或请求导致的问题。 修复有问题的代码,优化数据库查询。 |
数据库进程 (mysqld, postgres) |
慢查询、锁等待、全表扫描、没有索引。 | 使用 SHOW PROCESSLIST; (MySQL) 或 pg_stat_activity (PostgreSQL) 查看正在执行的查询。使用 EXPLAIN 分析慢查询的执行计划。为相关字段添加索引。 优化 SQL 语句。 |
| **Java 进程 |
