记录系统占用高

既然现场已经恢复,最好的办法就是部署一个“监控哨兵”脚本。这个脚本会每分钟检查一次系统 Load,一旦发现异常(比如 Load 超过你告警时的阈值),就立即抓取当时的进程、IO 和内核状态并保存到日志中。

我为你写了一个专门针对 Linux 环境(特别是像你这种 Master 节点)的排查脚本。


避免日志文件过大

方案一:使用 Linux 标准工具 logrotate (推荐)

这是最专业的方法。你可以告诉系统:“这个日志文件如果超过 10MB,就帮我切割并压缩,只保留最近的 5 份。”

  1. 创建配置文件:
    sudo vi /etc/logrotate.d/load_monitor
  2. 写入以下内容:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /var/log/load_troubleshoot.log {
    size 10M # 文件超过 10MB 就转储
    rotate 5 # 保留最近的 5 个归档日志
    compress # 压缩旧日志(节省空间)
    missingok # 如果文件丢失也不报错
    notifempty # 如果是空文件就不转储
    copytruncate # 关键:先复制再清空原文件,适合正在运行的脚本
    }

1. 自动化排查脚本 (load_monitor.sh)

你可以直接将以下代码保存到机器上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash

# 1. 设置阈值 (1分钟平均负载)
THRESHOLD=2.0
LOG_FILE="/var/log/load_troubleshoot.log"

# 2. 获取当前 Load 1min
LOAD_1MIN=$(uptime | awk -F'load average:' '{ print $2 }' | cut -d, -f1 | sed 's/ //g')

# 3. 使用 awk 比较浮点数 (返回 1 表示超标)
IS_HIGH=$(awk -v n1="$LOAD_1MIN" -v n2="$THRESHOLD" 'BEGIN {if (n1+0 >= n2+0) print 1; else print 0}')

if [ "$IS_HIGH" -eq 1 ]; then
{
echo "=========================================================="
echo "触发时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "当前负载: $LOAD_1MIN (阈值: $THRESHOLD)"
echo "----------------------------------------------------------"

echo "[1. CPU 占用前 10 进程]"
ps -eo pid,user,stat,pcpu,pmem,comm --sort=-pcpu | head -n 11

echo -e "\n[2. IO 阻塞 (D 状态) 进程及内核栈]"
# 查找 D 状态进程
D_PIDS=$(ps -eo pid,stat | grep -w D | awk '{print $1}')
if [ -z "$D_PIDS" ]; then
echo "当前无 D 状态进程"
else
for pid in $D_PIDS; do
echo "--- PID: $pid ---"
ps -p $pid -o user,stat,pcpu,comm
[ -f /proc/$pid/stack ] && cat /proc/$pid/stack
done
fi

echo -e "\n[3. 磁盘 IO 压力统计 (iostat)]"
# 执行 2 次取第 2 次的值比较准确
iostat -x 1 2 | awk '/^avg-cpu/ {p=1} p'

echo -e "\n[4. 最近 20 行系统关键日志]"
tail -n 20 /var/log/messages

echo -e "\n==========================================================\n"
} >> $LOG_FILE
fi

2. 部署步骤

  1. 创建文件并写入代码:
    vi /usr/local/bin/load_monitor.sh (粘贴上述代码)
  2. 赋予执行权限:
    chmod +x /usr/local/bin/load_monitor.sh
  3. 配置定时任务 (Crontab):
    执行 crontab -e,添加以下行(每分钟检查一次):
    1
    2
    * * * * * /usr/local/bin/load_monitor.sh


3. 这个脚本能帮你发现什么?

  • 如果是定时任务: 脚本会在 00:01 分运行,并在日志中记录下当时谁在吃 CPU。
  • 如果是 IO 阻塞: 脚本通过 ps ... grep D/proc/pid/stack 能直接告诉你,进程是不是卡在 NFSEtcd 的同步上。
  • 如果是存储性能问题: iostat 里的 %util 会暴露出磁盘是否已经到了物理瓶颈。

4. 立即手动执行一次看看效果

你可以先手动调低 THRESHOLD 值(比如调成 0.1)运行一下,看看 /var/log/load_troubleshoot.log 里的输出格式是否符合预期。

1
tail -n 100 /var/log/load_troubleshoot.log