以下是完整的安装与配置方案。该方案通过极简的 Bash 脚本监控内存,在可用内存低于 512 MiB 时强制触发内核 OOM Killer,从而避免系统陷入漫长的内存回收死等,保持桌面响应。
1. 开启 SysRq 权限(部分系统需要,可选)
内核必须允许接收手动触发 OOM 的指令。
bash
# 临时开启(立即生效)
echo 1 | sudo tee /proc/sys/kernel/sysrq
# 永久开启(重启后依然有效)
echo "kernel.sysrq=1" | sudo tee /etc/sysctl.d/99-sysrq.conf
sudo sysctl --system
2. 优化内核内存水位线(推荐)
提高内核保留的紧急空闲内存,促使后台回收线程提前工作,减少前台 GUI 进程卡顿。
bash
echo "vm.min_free_kbytes=524288" | sudo tee /etc/sysctl.d/99-min-free.conf
sudo sysctl --system
3. 部署监控脚本
创建一个纯 Bash 内建命令编写的脚本,每 0.1 秒检查一次可用内存。
bash
# 创建并写入脚本内容
sudo tee /usr/local/bin/oom-sysrq.sh > /dev/null << 'EOF'
#!/bin/bash
# 阈值:512 MiB (524288 kB)
THRESH=524288
# 触发后的冷却时间(秒)
COOLDOWN=5
while :; do
# 纯 Bash 内建读取,避免 fork 外部命令
while read -r key val _; do
case $key in
MemAvailable:) avail=$val ;;
esac
done < /proc/meminfo
if (( avail < THRESH )); then
# 强制触发内核 OOM Killer
echo f > /proc/sysrq-trigger
sleep "$COOLDOWN"
fi
# 0.1 秒检查一次
sleep 0.1
done
EOF
# 赋予执行权限
sudo chmod +x /usr/local/bin/oom-sysrq.sh
4. 配置 Systemd 服务
将脚本注册为系统服务,确保开机自启,并赋予其最高级别的 OOM 豁免权。
bash
# 创建服务文件
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
5. 验证配置
检查服务状态,确保其正在运行:
bash
systemctl status oom-sysrq.service
应显示绿色的 active (running)。
6. 查看触发记录
当脚本介入时,可以通过以下命令查看日志:
bash
# 查看内核的 OOM 记录(包含 "SysRq: Manual OOM execution" 字样即为脚本触发)
sudo dmesg -T | grep -i -E "sysrq|out of memory" | tail -10
7. 卸载与回退
如果未来不再需要此方案,可通过以下命令彻底清理:
bash
# 停止并禁用服务
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 rm -f /etc/sysctl.d/99-min-free.conf
sudo sysctl --system
# 清理 systemd 状态
sudo systemctl daemon-reload
sudo systemctl reset-failed