线上系统CPU,内存,硬件占用都很底,但就是会死机,SSH都无法连接,通过/var/log/messages查看到很多oom-killer的输出,原来单个进程占用太多的内存,被内核无情的KILL掉了,哎...
赶紧脑补一下OOM:
Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉。典型的情况是:某天一台机器突然ssh远程登录不了,但能ping通,说明不是网络的故障,原因是sshd进程被OOM killer杀掉了(多次遇到这样的假死状况)。重启机器后查看系统日志/var/log/messages会发现Out of Memory: Kill process 1865(sshd)类似的错误信息。
防止重要的系统进程触发(OOM)机制而被杀死:可以设置参数/proc/PID/oom_adj为-17,可临时关闭linux内核的OOM机制。内核会通过特定的算法给每个进程计算一个分数来决定杀哪个进程,每个进程的oom分数可以/proc/PID/oom_score中找到。我们运维过程中保护的一般是sshd和一些管理agent。
了解了原理之后,就可以写个SHELL脚本进行免疫了哈:
OMM单进程免疫脚本:
#!/bin/bash
supervisor_pid=`ps -ef |grep "supervisord"| head -n 1| awk '{print $2}'`
echo -17 > /proc/$supervisor_pid/oom_adj
webcron_pid=`ps -ef |grep "webcron"| head -n 1| awk '{print $2}'`
echo -17 > /proc/$webcron_pid/oom_adj
gs_pid=`ps -ef |grep "gs"| head -n 1| awk '{print $2}'`
echo -17 > /proc/$gs_pid/oom_adj
OOM进程批量免疫脚本:
#!/bin/bash
echo $(ps -ef | grep "php"| awk '{print $2}')>/tmp/pids.txt
for i in `cat /tmp/pids.txt`;
do
echo -17 > /proc/$i/oom_adj
if [ $? -eq 0 ];then
echo "Process $i OOM guard OK "|tee -a /tmp/oom_guard.log
else
echo "Process $i OOM guard false "|tee -a /tmp/oom_guard.log
fi
done
可以将以上脚本加入系统自启动或定时任务
当然还可以通过修改内核参数禁止OOM机制
# sysctl -w vm.panic_on_oom=1
vm .panic_on_oom = 1 / /1表示关闭,默认为0表示开启OOM
# sysctl -p
如果程序不存在内存溢出的话,可以将OOM机制关闭哈^_^