系统级内存管理工具-earlyoom
2022-06-27 14:39:07 阿炯

内存的管理在操作系统中一直都是一个重要的区域,虚拟内存的引入缓解了物理内存不足,牺牲部分性能可以换来整体系统的稳定运行与成本的节约,尤其是在物理内存昂贵年代。但话说回来,任何资源都有其稀缺性,内存尤其如此。内核开发人员一直在寻找改善低RAM环境中Linux交互性的方法,例如GNOME GLib的GMemoryMonitor,以及各发行厂商们也在积极探索使用哪些解决方案来解决内存不足的问题。前不久Ubuntu 22.04 LTS 版本的新功能:默认启用 systemd-oomd 以缓解内存不足的问题就导致情况有些失控,影响用户体验。

Linux发生内存溢出时,会触发OOM导致系统卡顿,这种情况可能会持续数分钟。相比进程被杀,卡顿更让人无法接受。最简单的评估Linux内存不足的方法就是直接观察已分配内存是否已经逼近上限,在逼近上限时,立刻处理掉最大内存消耗的进程,可以在死机的边缘将主机挽救回来。而Linux本身却没有这种在OOM早期就处理进程机制,只能等待极为缓慢 OOM过程。因此使用第三方工具来改善系统自带OOM功能了,做到早发现早处理,而EarlyOOM正是这样一个工具。

EarlyOOM是一个用户空间守护进程,用于检查内存量和交换频率,以便在内存压力过大导致Linux响应过慢或无响应时之前更快地触发Linux的内存不足杀手oom-killer。采用C语言开发并在MIT协议下授权使用。

官方介绍

earlyoom - The Early OOM Daemon.

The oom-killer generally has a bad reputation among Linux users. This may be part of the reason Linux invokes it only when it has absolutely no other choice. It will swap out the desktop environment, drop the whole page cache and empty every buffer before it will ultimately kill a process. At least that's what I think that it will do. I have yet to be patient enough to wait for it, sitting in front of an unresponsive system.

默认情况下,剩余可用物理内存小于 10% 和剩余交换内存小于10%时,就会触发早期OOM
SIGTERM when mem <= 10 % and swap <= 10 %
SIGKILL when mem <= 5 % and swap <= 5 %

如果觉得剩余内存保留太多,可以编辑 earlyoom 的配置文件来修改成指定的阀值。

在/etc/default/earlyoom中修改,完成后重启应用生效。

建议配置设置
-r 60 代表每60秒打印一次内存统计信息
-m 1 代表保留物理内存为1%
-s 5 代表保留交换内存为5%
–avoid '(^|/)(init|X|sshd)$' 代表任何时候不要杀死名字中带有 init,X,sshd 的这些进程

EARLYOOM_ARGS="-r 60 -m 1 -s 5 --avoid '(^|/)(init|X|sshd)$'"

#优先处理java或chromium名的应用进程
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"

名称来源自:/proc/PID/comm

运行如下命令启动 Early OOM
# earlyoom
earlyoom v1.2
mem  total: 3854 MiB, sending SIGTERM at 10 %, SIGKILL at  5 %
swap total: 3811 MiB, sending SIGTERM at 10 %, SIGKILL at  5 %
mem avail: 3307 of 3854 MiB (85 %), swap free: 3811 of 3811 MiB (99 %)
mem avail: 3307 of 3854 MiB (85 %), swap free: 3811 of 3811 MiB (99 %)
mem avail: 3307 of 3854 MiB (85 %), swap free: 3811 of 3811 MiB (99 %)

将会一直打印当前主机上有多少内存和交换区,以及有多少可用的内存和交换区。 如果可用的内存和交换区大小都低于 10%,Early OOM 将会自动杀死最大的进程,直到系统有足够的内存可以流畅的运行。也可以根据你的需求配置最小百分比值,设置最小的可用内存百分比运行:
earlyoom -m <PERCENT>

设置最小可用交换区百分比运行:
earlyoom -s <PERCENT>

帮助指令如下:
# earlyoom -h
earlyoom v1.2
Usage: earlyoom [OPTION]...

-m PERCENT[,KILL_PERCENT] set available memory minimum to PERCENT of total (default 10 %).
                            earlyoom sends SIGTERM once below PERCENT, then SIGKILL once below
                            KILL_PERCENT (default PERCENT/2).
-s PERCENT[,KILL_PERCENT] set free swap minimum to PERCENT of total (default 10 %)
-M SIZE[,KILL_SIZE]       set available memory minimum to SIZE KiB
-S SIZE[,KILL_SIZE]       set free swap minimum to SIZE KiB
-i                        user-space oom killer should ignore positive oom_score_adj values
-n                        enable notifications using "notify-send"
-N COMMAND                enable notifications using COMMAND
-d                        enable debugging messages
-v                        print version information and exit
-r INTERVAL               memory report interval in seconds (default 1), set to 0 to disable completely
-p                        set niceness of earlyoom to -20 and oom_score_adj to -1000
--prefer REGEX            prefer killing processes matching REGEX
--avoid REGEX             avoid killing processes matching REGEX
-h, --help                this help text

关于系统内置的 OOM killer

OOM killer也就是 Out Of Memory killer。它是一个由内核在可用内存非常低的时候使用的进程,其主要任务是不断的杀死进程,直到释放出足够的内存,使内核正在运行的其它进程能顺利运行。OOM killer 会找到系统中最不重要并且能释放出最多内存的进程,然后杀掉他们。在 /proc 目录下的 pid 目录中可以看到每个进程的 oom_score。

$ cat /proc/1029/oom_score
1

一个进程的 oom_score 的值越高,代表着它有大概率在系统内存耗尽的时候被 OOM killer 杀死。

Early OOM 的开发者称相对于内置的 OOM killer,Early OOM 有一个很大的优点。Early OOM 使用 /proc/*/status 而不是 echo f > /proc/sysrq-trigger这条命令会调用 OOM killer 杀死进程。开发者还表示,手动触发 OOM killer 在最新版本的 Linux 内核中很可能不会起作用。


最新版本:1.7


项目主页:https://github.com/rfjakob/earlyoom