WD My Cloud 的内存只有256M,在安装一系列应用之后,往往会导致内存不足,尤其是磁盘对拷的时候,很大的文件,往往会导致 Linux 内核的 OOM-Killer动作,导致 sshd ,Apache 等的服务被杀死,此时系统的指示灯是正常的,但是网络响应全无,只能强制断电。
先简单讲一下OOM-Killer的原理
OOM-killer:Out-of-Memory (OOM) Killer是一种保护机制,用于当内存严重不足时,为了系统的继续运转,内核迫不得已挑选一个进程,将其杀死,以释放内存,缓解内存不足的问题。
可以看出这种方式对进程的保护是有限的,不能完全的保护进程的运行。
OOM Killer的关闭与激活方式:
1 2 3 |
# echo "0" > /proc/sys/vm/oom-kill # echo "1″ > /proc/sys/vm/oom-kill |
在实际运营场景中,我们经常出现ssh连接不上服务器,但ping却是通的情况,这个时候很有可能是内存不够linux启动了oom-killer,系统根据一定的分数和机制来决定
随机杀掉一些程序释放物理内存(特别是我们后台需要大量共享内存而且用了mlock的程序),而sshd进程很可能就是被选中杀掉的进程,因此导致通过ssh登录不上。
这个时候基本上swap也被耗尽, 所有能释放内存的机制内核都已经尝试了。
而ping能够通,主要是因为ping其实是内核协议栈就直接回包了,不会走到用户态,所以还能证明机器还是活着的。
对于每个进程都有一个oom_score的属性/proc/PID/oom_score
oom- killer 会杀死oom_score较大的进程,当oom_score为0时禁止内核杀死该进程。
还有一个/proc/PID/oom_score_adj
一般来说,oom_adj的值越大,该进程被系统选中终止的可能就越高,当oom_adj=-17时,oom_score将变为0。
(要对某个进程进行OOM保护的话就直接向“/proc/pid/oom_adj”中写入“-17”即可。)
所以可以通过命令
1 |
$ echo 0 > /proc/PID/oom_score_adj |
来防止重要的进程被oom_killer杀死。
例如可以把sshd进程的oom_adj改为0 ,包括自己连接上的那个终端进程,这样你还可以执行一些运维工作。
既然了解到这些,那么操作方式就很简单了。
为了防止SSHD被杀死,可以在命令行中执行如下命令
1 |
$ pgrep -f "/usr/sbin/sshd" | while read PID; do echo -17 > /proc/$PID/oom_score_adj;done |
为保万无一失,利用Linux的计划任务cron来做一下定时检查。
1 |
$ sudo vim /etc/cron.d/sshd_oom_disabled |
里面内容如下
1 2 |
#/etc/cron.d/sshd_oom_disable */10**** root pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_score_adj;done |
表示每10分钟执行一次进程存在检查。