Ubuntu服务器cpu跑满排查 进程监控与性能优化实操教程

Ubuntu服务器cpu跑满排查 进程监控与性能优化实操教程

CPU 跑满,服务响应变慢甚至宕机

服务器 CPU 使用率突然飙升到 100% 是运维中非常常见的紧急情况。症状通常是:网站响应极慢甚至无法访问,SSH 登录也变得迟钝,服务器负载居高不下。

导致 CPU 跑满的原因多种多样:流量突增、死循环 Bug、CC 攻击、定时任务同时触发、MySQL 慢查询、内存不足触发频繁 swap 交换等。

本文提供一套系统化的排查流程,帮你在最短时间内定位 CPU 占用根因,并给出对应的优化方案。


一、第一步:快速确认 CPU 使用情况

使用 top 命令实时查看

top

top 界面关键信息解读:

  • 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

# 启动
htop

htop 提供彩色图形界面,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.conf
worker_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 = 3s
sudo 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 = 1
sudo 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
fi
sudo chmod +x /usr/local/bin/cpu_alert.sh

# 每5分钟检查一次
echo "*/5 * * * * root /usr/local/bin/cpu_alert.sh" | sudo tee /etc/cron.d/cpu_alert

CPU 排查流程速查

现象可能原因排查命令解决方向
Nginx 进程占用高CC 攻击 / 流量突增ss -s / Nginx 日志分析限流 / 高防 / 扩容
PHP-FPM 占用高代码死循环 / 插件冲突PHP 慢日志优化代码 / 禁用问题插件
MySQL 占用高慢查询 / 缺少索引SHOW PROCESSLIST添加索引 / 优化 SQL
CPU wa 值高内存不足频繁 Swapfree -h升级内存 / 减少进程数
定时任务时段峰值Cron 任务同时触发crontab -l错开执行时间
未知进程持续占用挖矿木马 / 异常程序ps aux / lsof -p PID立即终止并排查入侵

总结

CPU 排查的正确顺序:

  1. top / htop 确认负载和找出高 CPU 进程
  2. ps aux 确认进程身份和启动命令
  3. 根据进程类型(Nginx / PHP / MySQL / Cron)进入对应排查路径
  4. 查看对应日志(慢日志、访问日志、错误日志)定位根因
  5. 针对根因优化配置或修复代码
  6. 配置长期监控,提前发现下次异常

大多数情况下,CPU 跑满的根因在 30 分钟内可以定位并解决。如果问题持续出现,说明服务器配置已不满足业务需求,应考虑升级到更高配置。

如果你的 VPS 配置已成为性能瓶颈,IDC.Net 香港独立服务器提供独占物理 CPU 的独立服务器方案,从 E3 四核到高性能多核配置均有,月付 299 元起,不存在 VPS 的”吵闹邻居”问题,CN2 GIA 直连大陆,支持支付宝 / USDT 付款,按月付款灵活升级。

Telegram