问题
如果进程突然被杀死没有应用日志,而且进程占用内存过高,考虑是否是由于linux OOM killer机制杀死的。
原因
linux内核有个OOM Killer机制会在内存不够分配的时候触发,选择性的杀死一些内存占用最高的进程腾出内存空间,保证系统正常运行。详细请看https://blog.csdn.net/top_explore/article/details/107733974。
确定问题
查看linux内核日志:
grep "Out of memory" /var/log/messages
如果:图片摘自https://www.cnblogs.com/duanxz/p/10185946.html
则说明是OOM killer杀死进程
解决,防止OOM Killer的方法
综上所述,知道了OOM killer的原理以及约束后,可以总结出以下几种方法来避免进程被OOM killer杀死。
1.修改Overcommit策略为1或2。(不推荐)
2.修改panic_on_oom参数为2,直接死机(不推荐)。
3.修改进程oom_adj和oom_score_adj来降低oom_score的得分,降低被OOM killer选中的几率。
oom_adj可选值:[-17,15] -17表示禁止OOM killer
修改方式
echo -17 > /proc/$PID/oom_adj
oom_score_adj可选值[-1000,1000]。0表示用户不调整oom_score,负值表示要在实际打分值上减去一个折扣,正值表示要惩罚该task,也就是增加该进程的oom_score。
例如如果oom_score_adj设定-500,那么表示实际分数要打五折(基数是totalpages),也就是说该任务实际使用的内存要减去可分配的内存上限值的一半。
修改方式:
echo -500 > /proc/$PID/oom_score_adj
了解了oom_score_adj和oom_score之后,应该是尘埃落定了,oom_adj是一个旧的接口参数,其功能类似oom_score_adj,为了兼容,目前仍然保留这个参数,当操作这个参数的时候,kernel实际上是会换算成oom_score_adj,有兴趣的同学可以自行了解,这里不再细述了。
4.降低应用程序申请的内存大小,在足够使用的情况下,尽量少申请内存,内存越低得到的分数越低,越不容易被选中。
查看所有进程的oom_score排行前十的进程
#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
printf "%2d %5d %s\n" \
"$(cat $proc/oom_score)" \
"$(basename $proc)" \
"$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10