Ubuntu服务器cpu跑满排查 进程监控与性能优化实操教程
CPU 跑满,服务响应变慢甚至宕机
服务器 CPU 使用率突然飙升到 100% 是运维中非常常见的紧急情况。症状通常是:网站响应极慢甚至无法访问,SSH 登录也变得迟钝,服务器负载居高不下。
导致 CPU 跑满的原因多种多样:流量突增、死循环 Bug、CC 攻击、定时任务同时触发、MySQL 慢查询、内存不足触发频繁 swap 交换等。
本文提供一套系统化的排查流程,帮你在最短时间内定位 CPU 占用根因,并给出对应的优化方案。
一、第一步:快速确认 CPU 使用情况
使用 top 命令实时查看
toptop 界面关键信息解读:
- load average:系统平均负载,三个数字分别代表过去 1 分钟、5 分钟、15 分钟的平均负载。负载值超过 CPU 核心数说明系统过载(如 4 核服务器负载超过 4.0 就需要关注)
- %Cpu(s):CPU 各类使用率分布,重点关注
us(用户态)和sy(内核态) - 进程列表:按 CPU 使用率降序排列,第一行就是当前 CPU 占用最高的进程
在 top 界面中,按 1 可以查看每个 CPU 核心的使用率,便于判断是单核打满还是整体过载。
使用 htop(更直观)
# 安装 htop
sudo apt install htop -y
# 启动
htophtop 提供彩色图形界面,CPU 使用率以进度条形式展示,进程列表支持鼠标点击排序,比 top 更直观。按 F6 可以按 CPU 使用率排序。
查看系统整体负载历史
# 查看最近的系统负载历史
uptime
# 查看过去一段时间的资源使用统计(需安装 sysstat)
sudo apt install sysstat -y
sar -u 1 10二、第二步:定位高 CPU 进程
找出 CPU 占用最高的进程
# 按 CPU 使用率排序,显示前10个进程
ps aux --sort=-%cpu | head -11
# 持续监控每秒 CPU 占用
pidstat 1 10定位具体是哪个用户/应用
# 查看某个进程的详细信息(替换 PID 为实际进程号)
ls -la /proc/PID/exe
cat /proc/PID/cmdline | tr '\0' ' '
# 查看该进程打开的文件和网络连接
lsof -p PID | head -30查找僵尸进程
# 僵尸进程本身不占 CPU,但可能导致父进程异常
ps aux | grep 'Z'三、常见高 CPU 原因与对应解决方案
原因一:Nginx 进程 CPU 异常高
通常是 CC 攻击或流量突增导致。先确认是否受到攻击:
# 查看当前连接数
ss -s
# 查看请求量最大的 IP
tail -n 5000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20如确认是正常流量增长导致,优化 Nginx 配置提升处理能力:
sudo nano /etc/nginx/nginx.confworker_processes auto; # 自动匹配 CPU 核心数
worker_rlimit_nofile 65535; # 提升文件描述符上限
events {
worker_connections 4096; # 每个 worker 最大连接数
use epoll; # 使用高效的 epoll 模型
multi_accept on; # 一次接受多个连接
}
http {
keepalive_timeout 30; # 适当降低 keepalive 超时
keepalive_requests 1000;
# 开启 Gzip 压缩降低传输量
gzip on;
gzip_comp_level 5;
gzip_types text/plain text/css application/json application/javascript;
# 开启文件缓存
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
}sudo nginx -t && sudo systemctl reload nginx原因二:PHP-FPM 进程 CPU 异常高
通常是 PHP 代码存在死循环、慢查询或 WordPress 插件冲突。
查看 PHP-FPM 慢日志(需先开启):
sudo nano /etc/php/8.1/fpm/pool.d/www.conf# 开启慢日志,记录执行超过3秒的请求
slowlog = /var/log/php-fpm-slow.log
request_slowlog_timeout = 3ssudo systemctl restart php8.1-fpm查看慢日志找出问题脚本:
tail -f /var/log/php-fpm-slow.log优化 PHP-FPM 进程数配置:
# 在 www.conf 中调整进程管理方式
pm = dynamic
pm.max_children = 20 # 根据内存调整,每个进程约占 30-50MB
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500 # 每个进程处理500个请求后重启,防止内存泄漏原因三:MySQL CPU 异常高(慢查询)
开启 MySQL 慢查询日志定位问题 SQL:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf# 开启慢查询日志
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # 记录执行超过1秒的查询
log_queries_not_using_indexes = 1sudo systemctl restart mysql分析慢查询日志:
# 统计最慢的10条查询
sudo mysqldumpslow -s t -t 10 /var/log/mysql/slow.log实时查看当前正在执行的查询:
mysql -u root -p -e "SHOW PROCESSLIST;"对于频繁查询但缺少索引的表,添加索引是最直接的优化方式:
-- 查看某张表的现有索引
SHOW INDEX FROM your_table;
-- 为常用查询字段添加索引
ALTER TABLE your_table ADD INDEX idx_column_name (column_name);原因四:定时任务(Cron)同时触发
多个资源密集型定时任务同时运行会导致 CPU 瞬间峰值。
# 查看当前所有 crontab
crontab -l
sudo crontab -l
sudo cat /etc/crontab
sudo ls /etc/cron.d/优化方案:将各任务的执行时间错开,避免同时触发。例如:
# 错误:所有任务都在每天凌晨0点执行
0 0 * * * /script1.sh
0 0 * * * /script2.sh
0 0 * * * /script3.sh
# 正确:错开执行时间
0 0 * * * /script1.sh
15 0 * * * /script2.sh
30 0 * * * /script3.sh原因五:内存不足触发频繁 Swap
当物理内存耗尽,系统开始使用磁盘上的 Swap 空间,磁盘 I/O 速度远低于内存,会导致 CPU 等待 I/O 增加,表现为系统整体变慢、CPU wa(I/O 等待)指标升高。
# 查看内存和 Swap 使用情况
free -h
# 查看 Swap 使用最多的进程
for file in /proc/*/status; do
awk '/VmSwap|Name/{printf $2 " " $3}END{print ""}' $file
done | sort -k 2 -n -r | head -10解决方案:升级内存配置,或优化应用内存使用,减少进程数量。
四、使用 perf 进行深度分析(进阶)
当 top 和 ps 无法定位根因时,使用 perf 进行性能剖析:
sudo apt install linux-tools-common linux-tools-generic -y
# 对整个系统采样30秒
sudo perf top
# 对特定进程采样(替换 PID)
sudo perf record -g -p PID sleep 30
sudo perf report五、长期监控方案
单次排查解决问题后,需要建立长期监控,提前发现 CPU 异常趋势。
用 sysstat 记录历史数据
# 启用 sysstat 定期采集
sudo systemctl enable sysstat
sudo systemctl start sysstat
# 查看过去24小时的CPU使用率统计
sar -u简单的 CPU 告警脚本
sudo nano /usr/local/bin/cpu_alert.sh#!/bin/bash
CPU_THRESHOLD=80
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1 | cut -d',' -f1)
CPU_INT=${CPU_USAGE%.*}
if [ "$CPU_INT" -gt "$CPU_THRESHOLD" ]; then
echo "$(date): CPU usage is ${CPU_USAGE}%, exceeded threshold ${CPU_THRESHOLD}%" >> /var/log/cpu_alert.log
fisudo chmod +x /usr/local/bin/cpu_alert.sh
# 每5分钟检查一次
echo "*/5 * * * * root /usr/local/bin/cpu_alert.sh" | sudo tee /etc/cron.d/cpu_alertCPU 排查流程速查
| 现象 | 可能原因 | 排查命令 | 解决方向 |
|---|---|---|---|
| Nginx 进程占用高 | CC 攻击 / 流量突增 | ss -s / Nginx 日志分析 | 限流 / 高防 / 扩容 |
| PHP-FPM 占用高 | 代码死循环 / 插件冲突 | PHP 慢日志 | 优化代码 / 禁用问题插件 |
| MySQL 占用高 | 慢查询 / 缺少索引 | SHOW PROCESSLIST | 添加索引 / 优化 SQL |
| CPU wa 值高 | 内存不足频繁 Swap | free -h | 升级内存 / 减少进程数 |
| 定时任务时段峰值 | Cron 任务同时触发 | crontab -l | 错开执行时间 |
| 未知进程持续占用 | 挖矿木马 / 异常程序 | ps aux / lsof -p PID | 立即终止并排查入侵 |
总结
CPU 排查的正确顺序:
top/htop确认负载和找出高 CPU 进程ps aux确认进程身份和启动命令- 根据进程类型(Nginx / PHP / MySQL / Cron)进入对应排查路径
- 查看对应日志(慢日志、访问日志、错误日志)定位根因
- 针对根因优化配置或修复代码
- 配置长期监控,提前发现下次异常
大多数情况下,CPU 跑满的根因在 30 分钟内可以定位并解决。如果问题持续出现,说明服务器配置已不满足业务需求,应考虑升级到更高配置。
如果你的 VPS 配置已成为性能瓶颈,IDC.Net 香港独立服务器提供独占物理 CPU 的独立服务器方案,从 E3 四核到高性能多核配置均有,月付 299 元起,不存在 VPS 的”吵闹邻居”问题,CN2 GIA 直连大陆,支持支付宝 / USDT 付款,按月付款灵活升级。