Abel'Blog

我干了什么?究竟拿了时间换了什么?

0%

调查服务器CPU过高

**CPU“偶尔飙高”**这种,最怕的就是:你不在现场,它已经恢复了,然后啥线索都没留下。

你有 root 权限,这就很爽了,能把事情一次性“抓现行”。我按 从快到准 给你一套实战路线,你可以直接照着来。

一、先搞清楚:CPU 是“谁”在高?

1️⃣ 实时看(马上用)

top

重点看这几列:
• %CPU:谁在吃
• us / sy / wa
• us 高:用户态程序(你的服务、Java、Go、Node)
• sy 高:内核 / 系统调用
• wa 高:I/O 卡住(磁盘 / 网络)

👉 如果你看到的是 Java 300% / postgres 200%,事情就简单多了。

更推荐:

htop

(可视化 + 能看到线程)

二、问题在于:你不在的时候它才高

所以我们要 “持续采样 + 留证据”

三、必装工具(root 权限必备)

apt install -y sysstat dstat htop

yum install -y sysstat dstat

四、持续监控 CPU(核心)

1️⃣ 开启 sysstat(非常重要)

systemctl enable sysstat
systemctl start sysstat

它会每 10 分钟自动采样一次,数据保存在:

/var/log/sysstat/

2️⃣ 事后回看 CPU 历史(关键)

看某一天 CPU 是否异常:

sar -u -f /var/log/sysstat/sa05

重点关注:
• %usr
• %sys
• %iowait
• %idle

如果 %idle 掉到 0,那就是满负载了。

五、定位到“哪个进程”

1️⃣ 看历史中哪个进程吃 CPU(神器)

sar -q -f /var/log/sysstat/sa05

2️⃣ 按进程统计(更狠)

pidstat -u 1

持续输出:
• 哪个 PID
• 每秒吃多少 CPU

如果你怀疑是 Java / PostgreSQL:

pidstat -u -p $(pgrep java) 1
pidstat -u -p $(pgrep postgres) 1

六、CPU 高的时候自动抓现场(推荐你一定要做)

方案:超过 80% 自动记录 top

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat << 'EOF' > /root/cpu_watch.sh
#!/bin/bash
while true; do
CPU=$(top -bn1 | awk '/Cpu/ {print 100 - $8}')
if (( $(echo "$CPU > 80" | bc -l) )); then
echo "==== $(date) CPU=$CPU ====" >> /var/log/cpu_spike.log
top -b -n 1 >> /var/log/cpu_spike.log
fi
sleep 10
done
EOF

chmod +x /root/cpu_watch.sh
nohup /root/cpu_watch.sh &

📌 你之后只需要看:

less /var/log/cpu_spike.log

就能知道:

是哪一个进程、哪个线程,把 CPU 干爆了

七、如果是 Java / Go / PostgreSQL(你很可能会遇到)

🔥 Java
• top 里看到 Java 高
• 用:

top -H -p

找线程 → 再用 jstack

🔥 PostgreSQL(你最近就老在搞这个 😄)

1
2
3
SELECT pid, query, state
FROM pg_stat_activity
WHERE state != 'idle';

配合系统:

pidstat -u -p $(pgrep postgres) 1

🔥 Go 程序
• 大概率是:
• 死循环
• goroutine 泄露
• GC 抖动
• 可以临时加:

curl http://localhost:6060/debug/pprof/profile?seconds=30 > cpu.pprof

八、我给你一个最省事组合

如果你只想 今天就落地:

✅ sysstat
✅ pidstat
✅ 自动 cpu_watch.sh

这三样,99% 的 CPU 问题都能破案

九、下一步我可以直接帮你“对症下药”

你可以直接告诉我其中一个👇
• CPU 高的时候 top 里看到的进程名
• 是 Java / PostgreSQL / Go / Node
• 是 us 高 / sy 高 / wa 高