运维脚本无法阻止OOM Killer,但可通过实时监控MemAvailable与Committed_AS、分级响应、被杀后秒级取证、关键进程oom_score_adj调权及业务特征规避(如清理slab、调优TCP参数、检测堆外泄漏)来主动干预、降低影响并辅助定位。

运维脚本不能“阻止”OOM Killer杀进程,但可以提前感知、快速响应、降低影响、辅助定位。核心思路是:不等被杀,主动干预;不靠重启,重在收敛;不止于告警,要留取证线索。
实时监控内存水位,触发分级响应
脚本应持续读取 /proc/meminfo 中的关键字段,而非依赖 free -h 的 available 估算值:
- 重点监控
MemAvailable(真实可用内存)和Committed_AS(已承诺虚拟内存),当Committed_AS > CommitLimit时,OOM 已不可逆,必须立即动作 - 设置三级阈值:预警(MemAvailable < 512MB)、干预(MemAvailable < 256MB 或 Committed_AS/CommitLimit > 0.95)、熔断(MemAvailable < 64MB)
- 达到干预阈值时,自动执行:限制新连接(如
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 100 -j DROP)、降级非核心服务(systemctl stop log-collector.service)、触发紧急 GC(对 Java 进程发kill -SIGUSR2若已配置)
被杀后秒级捕获现场,固化关键证据
OOM 发生后,内核日志转瞬即逝,脚本需监听并即时保存:
- 用
dmesg -T | grep -i "killed process\|out of memory" | tail -n 1每 5 秒轮询一次,一旦命中,立刻执行快照命令 - 同步采集:当前所有进程的 PSS 内存分布(
smem -k -c "pid user command pss uss" | sort -k4nr)、各进程 slab 使用(cat /proc/PID/smaps | grep -E "^Slab:|^SReclaimable:")、cgroup 内存限制(cat /sys/fs/cgroup/memory/$(ps -o cgroup= -p $PID)/memory.max 2>/dev/null) - 将结果压缩为带时间戳的归档(如
oom-20260916-010322.tar.gz),上传至独立日志服务器,避免本地磁盘被写满
对核心业务进程做轻量级防护
不推荐全局禁用 OOM Killer,而应在脚本中为关键进程动态设置保护权重:
- 启动关键服务(如 MySQL、Nginx master)后,立即执行:
echo -1000 > /proc/$(pgrep -f "mysqld" | head -1)/oom_score_adj - 注意:该操作需 root 权限,且仅对当前进程有效;若进程重启,脚本需再次设置(建议集成进 systemd service 的 ExecStartPost)
- 避免对 worker 进程(如 nginx worker、php-fpm child)设 -1000,否则可能因内存耗尽导致整个服务僵死;可设为 -500 作折中
结合业务特征做针对性规避
很多 OOM 并非真缺内存,而是特定行为诱发:
- 若脚本检测到
SlabUnreclaim持续上升(尤其dentry或skbuff_head_cache),自动触发清理:echo 2 > /proc/sys/vm/drop_caches(仅临时缓解,需后续升级内核或 LB 软件) - 若发现大量短连接堆积(
netstat -ant | grep :80 | wc -l > 5000),自动调整内核参数:sysctl -w net.ipv4.tcp_fin_timeout=30,并记录连接来源 IP 前十供人工分析 - 对 Java 类服务,检查
/proc/PID/status中VmData是否异常膨胀,若远超VmRSS,提示可能存在堆外内存泄漏,建议追加 JVM 参数-XX:MaxDirectMemorySize


















