应先用nproc获取cpu核心数,以$cpu_count*1.5为阈值比较/proc/loadavg第二字段(5分钟负载),用bc做浮点比较,超标后按java/jstack/jmap、支持sigusr2的服务或gcore优先级执行带超时的dump,并加sleep、文件锁和磁盘空间检查防反效果。

怎么用 shell 脚本实时判断 load average 是否超标
Linux 的 uptime 或 cat /proc/loadavg 输出的前三个数字(1/5/15 分钟平均负载)得跟 CPU 核心数比才有意义。直接比绝对值 5 或 10 是错的——4 核机器 load=6 已明显过载,32 核机器 load=6 可能毫无压力。
实操建议:
- 先用
nproc获取逻辑 CPU 数(含超线程),记为cpu_count - 监控阈值设为
cpu_count * 1.5(可调),只看 5 分钟负载(/proc/loadavg第二个字段)更稳,避免瞬时毛刺误触发 - 别用
uptime | awk '{print $10}'这类脆弱解析——不同 locale 下冒号位置、空格数都可能变
负载超标后怎么安全触发 gcore 或 kill -SIGUSR2 Dump
不能粗暴 kill -ABRT 主进程,容易丢现场;优先用调试器抓内存快照,或让应用自己响应信号生成 dump。
实操建议:
- 对 Java 进程:用
jstack -l <pid> > /var/log/dump/jstack_$(date +%s).log</pid>+jmap -dump:format=b,file=/var/log/dump/heap_$(date +%s).hprof <pid></pid> - 对支持
SIGUSR2的服务(如 Nginx、某些 Go 服务):执行kill -USR2 <pid></pid>,前提是它已实现该信号的 dump 逻辑 - 通用 fallback:用
gcore -o /var/log/dump/core_$(date +%s) <pid></pid>,但注意gcore会暂停进程几秒,生产环境慎用 - 所有 dump 命令必须加超时,比如
timeout 30s jmap ...,防止卡死脚本
怎么避免反复触发、写满磁盘或干扰正常运维
连续 dump 几次就可能占掉几十 GB,且高频检测本身也会抬高负载——这是最常被忽略的反效果。
实操建议:
- 每次 dump 后强制 sleep 至少 300 秒(
sleep 300),用文件锁(flock)或时间戳文件防并发 - dump 目录挂载独立分区,或用
find /var/log/dump -name 'core_*' -mmin +1440 -delete每天清理 24 小时前的文件 - 脚本开头检查磁盘剩余空间:
df /var/log | awk 'NR==2 {print $5}' | sed 's/%//',低于 15% 直接 exit - 不要把监控脚本塞进
crontab每分钟跑——改用while true; do ...; sleep 60; done更可控
为什么 /proc/loadavg 解析要小心小数点和字段顺序
/proc/loadavg 格式是 0.12 0.08 0.03 1/123 12345,五个字段间空格数不固定,第三字段是 15 分钟负载,第二才是 5 分钟——很多人写成 awk '{print $1}' 就错了。
实操建议:
- 用
awk '{print $2}' /proc/loadavg | sed 's/,/./'取 5 分钟值,并兼容某些 locale 的逗号小数点 - 用
bc做浮点比较:echo "$load > $threshold" | bc -l,别用[ "$load" -gt "$threshold" ](bash 不支持小数) - 加一句
set -o pipefail在脚本开头,确保awk或sed失败时整个条件判断为 false
真正难的不是取 load 值或发信号,而是让 dump 行为本身不成为新的故障源——磁盘、CPU、进程暂停,三者只要一个失控,监控脚本就会从医生变成病根。











