使用自定义bash脚本预防oom卡死 v2

14 阅读3分钟

前言:首先,这只是个练习脚本,很多不完善的地方,仅供学习使用,出事了我不管啊

OOM SysRq 防卡死方案

该方案通过极简的 Bash 脚本监控内存,在物理空闲内存低于 256 MiB 时强制触发内核 OOM Killer,从而避免系统陷入内存回收死等,保持桌面响应。

原理说明

为什么用 MemFree 而不是 MemAvailable?

  • MemFree:物理空闲内存,直接反映真实状态
  • MemAvailable:包含可回收缓存,可能"虚高"掩盖风险
  • 当 MemFree < 256MiB 时,系统确实已无退路

看门狗的作用

  • 作为最后防线,防止系统陷入内存回收死等
  • 当所有回收手段都耗尽时,触发 OOM Killer 杀进程释放内存
  • 256MiB 是"已经没招了"的信号,触发即正确

安装步骤

1. 开启 SysRq 权限(不一定需要)

内核必须允许接收手动触发 OOM 的指令。

# 临时开启(立即生效)
echo 1 | sudo tee /proc/sys/kernel/sysrq

# 永久开启(重启后依然有效)
echo "kernel.sysrq=1" | sudo tee /etc/sysctl.d/99-sysrq.conf
sudo sysctl --system

2. 部署监控脚本

创建一个 Bash 脚本,每 0.1 秒检查一次物理空闲内存。

sudo tee /usr/local/bin/oom-sysrq.sh > /dev/null << 'EOF'
#!/bin/bash
# 触发阈值:256 MiB (262144 kB)
THRESH=262144

while :; do
    while read -r key val _; do
        case $key in
            MemFree:) free=$val ;;
        esac
    done < /proc/meminfo

    if (( free < THRESH )); then
        # 强制触发内核 OOM Killer
        echo f > /proc/sysrq-trigger
    fi

    # 0.1 秒检查一次
    sleep 0.1
done
EOF

# 赋予执行权限
sudo chmod +x /usr/local/bin/oom-sysrq.sh

4. 配置 Systemd 服务

将脚本注册为系统服务,确保开机自启,并赋予其最高级别的 OOM 豁免权。

sudo tee /etc/systemd/system/oom-sysrq.service > /dev/null << 'EOF'
[Unit]
Description=Trigger Kernel OOM via SysRq when memory is low
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/local/bin/oom-sysrq.sh
Restart=always
RestartSec=2
# 保护脚本自身不被 OOM 杀死
OOMScoreAdjust=-1000
# 在内存压力下优先获得 CPU 调度
Nice=-10
# 限制脚本自身的最大内存占用
MemoryMax=32M

[Install]
WantedBy=multi-user.target
EOF

# 重新加载 systemd 并启动服务
sudo systemctl daemon-reload
sudo systemctl enable --now oom-sysrq.service

验证配置

检查服务状态

systemctl status oom-sysrq.service

应显示绿色的 active (running)

查看当前内存状态

free -h
# 观察 MemFree 是否保持在较高水位

查看触发记录

当脚本介入时,可以通过以下命令查看日志:

# 查看内核的 OOM 记录
sudo dmesg -T | grep -i -E "sysrq|out of memory" | tail -10

卸载与回退

如果未来不再需要此方案,可通过以下命令彻底清理:

# 停止并禁用服务
sudo systemctl disable --now oom-sysrq.service

# 删除脚本和服务文件
sudo rm -f /usr/local/bin/oom-sysrq.sh
sudo rm -f /etc/systemd/system/oom-sysrq.service

# 恢复内核参数
sudo rm -f /etc/sysctl.d/99-sysrq.conf
sudo sysctl --system

# 清理 systemd 状态
sudo systemctl daemon-reload
sudo systemctl reset-failed

配置总结

项目说明
判断字段MemFree物理空闲内存
阈值256MB最后防线
检查间隔0.1秒每秒10次
触发方式SysRq直接触发内核 OOM

触发链条

正常状态:
  MemFree >> 256MiB → 看门狗睡觉 → 系统正常运行

极端场景:
  swap 满 → kswapd 换不动 → cache 被榨干 → MemFree 开始跌
  → 跌破 256MiB → 看门狗触发 → sysrq f 杀进程 → 释放内存 → 系统恢复