Linux中的Out Of Memory(OOM) Killer功能是一种确保系统内存足够的最终手段,可以在耗尽系统内存或交换区后,按某种算法判断占用系统最多资源的进程,向进程发送信号,强制终止该进程。
简单来说该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉。
这个功能即使在无法释放内存的情况下,也能够重复进行确保内存的处理过程,防止系统停滞,还可以找出过度消耗内存的进程。
典型的情况是:某天一台机器突然ssh远程登录不了,但能ping通,说明不是网络的故障或者机器down掉,很大可能是sshd进程被 OOM killer杀掉了。
重启机器后查看系统日志/var/log/messages会发现 Out of Memory: Kill process 247(sshd)类似的错误信息。
还有另外一种情况也会导致能ping不能ssh,就是网络连接过多把系统文件描述符资源耗尽,这里暂时不考虑这种情况。
而在使用vip的高可用方案中,这种情况也很容易出现脑裂的现象。
防止重要的系统进程触发(OOM)机制而被杀死:可以设置参数/proc/PID/oom_adj为-17,可临时关闭linux内核的OOM机制。内核会通过特定的算法给每个进程计算一个分数来决定杀哪个进程,每个进程的oom分数可以/proc/PID/oom_score中找到。
我们认为重要的进程有sshd,或者一些监控守护进程,大家可以根据自己实际情况选择需要保护的进程。
保护某个进程不被内核杀掉可以这样操作:
echo -17 > /proc/$PID/oom_adj
pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_adj;done
至于为什么用-17而不用其他数值(默认值为0),这个是由linux内核定义的,查看内核源码可知:
以linux- 3.3.6版本的kernel源码为例,路径为linux-3.6.6/include/linux/oom.h,阅读内核源码可知oom_adj的可调 值为15到-16,其中15最大-16最小,-17为禁止使用OOM。oom_score为2的n次方计算出来的,其中n就是进程的oom_adj值,所 以oom_score的分数越高就越会被内核优先杀掉。
当然还可以通过修改内核参数禁止OOM机制
# sysctl -w vm.panic_on_oom=1 vm.panic_on_oom = 1 //1表示关闭,默认为0表示开启OOM # sysctl -p
命令行参数输入占用内存大小N,根据自身实验环境的物理内存大小来设置,例如我的实验环境为内存4G,设为4G就足够了
代码命名为mem.c,编译方法 gcc -o mem mem.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #define PAGE_SZ (1<<12) int main(int argc, char* argv[]) { int i; if (argc != 2) return 0; int gb = atoi(argv[1]); for (i = 0; i < ((unsigned long)gb<<30)/PAGE_SZ ; ++i) { void *m = malloc(PAGE_SZ); if (!m) break; memset(m, 0, 1); } printf("allocated %lu MB\n", ((unsigned long)i*PAGE_SZ)>>20); getchar(); return 0; }
如果不执行任何操作的话,直接运行结果会发现系统自动oom掉这个进程
如果我们进行以下操作,把进程优先级设置为-17
pgrep -f "mem" | while read PID; do echo -17 > /proc/$PID/oom_adj;done
一个最简单的测试触发OOM的方法,可以把某个进程的oom_adj设置到15(最大值),最容易触发。然后执行以下命令:
echo f > /proc/sysrq-trigger
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/jeffreynicole/article/details/47263235