当我在服务器上运行一个不太重要的进程时,它的内存使用量会随实际情况不断发生变化,当它的内存超过某个阈值时,我想要 kill 掉它并重启该进程。为了满足我这个需求,我了解到了 earlyoom
这个程序。
earlyoom
是一个用于 Linux 的内存不足 (OOM) 守护进程。它在系统内存和交换空间不足时提前终止内存占用最大的进程,从而避免系统陷入完全无响应的状态。它的全称是 “Early OOM Daemon”,其中 OOM 代表 “Out Of Memory”。本文将介绍 earlyoom
的安装、配置和使用方法。
什么是 earlyoom?
在 Linux 系统中,默认的 OOM 机制只有在内存和交换空间完全耗尽后才会触发,这通常会导致系统变得非常缓慢甚至完全无响应。earlyoom
的设计初衷是通过更早地检测内存和交换空间不足的情况,提前终止高内存占用的进程,从而保持系统的响应速度。
earlyoom
每秒最多检查 10 次内存和交换空间的使用情况。如果可用内存和可用交换空间均低于 10%,则终止内存占用最大的进程。这个阈值可以通过命令行参数进行配置。
earlyoom 的主要功能和特点
- 监控内存使用情况:earlyoom 会持续监控系统的可用内存和交换内存。通过定期检查内存使用情况,它能够在内存过低时及时采取措施。
- 主动释放内存:当系统内存降至预设的阈值以下时,earlyoom 会主动终止内存占用最高的进程。这比传统的 Linux 内核 OOM 杀手更早地介入,减少系统变得完全无响应的风险。
- 可配置性:用户可以通过命令行参数或配置文件自定义 earlyoom 的行为,包括设定内存和交换内存的阈值,选择是否终止内存占用最高的进程或是直接重启系统。
- 轻量级和高效:earlyoom 设计为一个轻量级的守护进程,占用系统资源非常少,适合在各种环境下运行。
- 日志和通知:earlyoom 会记录所有的内存监控和进程终止操作,并可以配置为在内存过低时发送通知,方便管理员及时了解系统状态。
earlyoom 的使用场景
- 避免系统冻结:在 Linux 系统中,当内存资源耗尽时,内核的 OOM (Out of Memory) Killer 会启动,尝试释放内存。默认情况下,OOM Killer 会在系统内存极度不足时才启动,这可能导致系统变得非常缓慢或完全无响应,用户无法进行操作。earlyoom 通过在内存和交换空间较低时更早地杀死进程,防止系统冻结,提高系统的稳定性和响应性。
- 提高系统的可用性:对于一些关键的服务器或应用场景,确保系统的稳定性至关重要。earlyoom 可以在内存紧张之前采取措施,避免系统进入不可操作的状态,尤其是在资源使用高峰期。
- 开发和测试环境:在开发和测试环境中,可能会出现由于内存泄漏或其他原因导致内存迅速耗尽的情况。使用 earlyoom 可以模拟和测试系统在低内存条件下的表现,确保应用程序能够在这些条件下稳定运行。
如何安装 earlyoom
从源码编译
首先,克隆 earlyoom
的 GitHub 仓库并进入项目目录:
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
然后,编译项目:
make
可选:运行集成的自测试:
make test
最后,使用 systemd
或 init.d
将 earlyoom
注册为系统服务:
sudo make install # systemd
sudo make install-initscript # non-systemd
使用包管理器安装
Debian 和 Ubuntu
对于 Debian 10+ 和 Ubuntu 18.04+,可以直接安装 earlyoom
包:
sudo apt install earlyoom
Fedora 和 RHEL 8
对于 Fedora 和 RHEL 8(需要 EPEL):
sudo dnf install earlyoom
sudo systemctl enable --now earlyoom
Arch Linux
对于 Arch Linux:
sudo pacman -S earlyoom
sudo systemctl enable --now earlyoom
其他发行版的安装方法请参阅 repology 页面。
如何使用 earlyoom
启动 earlyoom
可执行文件:
./earlyoom
它会显示内存和交换空间的使用情况,并在内存和交换空间不足时终止进程。以下是一个示例输出:
earlyoom v1.8
mem total: 23890 MiB, user mem total: 21701 MiB, swap total: 8191 MiB
sending SIGTERM when mem avail <= 10.00% and swap free <= 10.00%,
SIGKILL when mem avail <= 5.00% and swap free <= 5.00%
mem avail: 20012 of 21701 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%)
mem avail: 20031 of 21721 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%)
mem avail: 20033 of 21723 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%)
[...]
命令行选项
earlyoom
支持多种命令行选项,以下是常用选项的说明:
earlyoom v1.8
Usage: ./earlyoom [OPTION]...
-m PERCENT[,KILL_PERCENT] 设置可用内存最小百分比 (默认 10%)。
低于此值发送 SIGTERM 信号,低于 KILL_PERCENT 时发送 SIGKILL 信号 (默认 PERCENT/2)。
-s PERCENT[,KILL_PERCENT] 设置可用交换空间最小百分比 (默认 10%)。
-M SIZE[,KILL_SIZE] 设置可用内存最小值 (以 KiB 计)。
-S SIZE[,KILL_SIZE] 设置可用交换空间最小值 (以 KiB 计)。
-n 启用 d-bus 通知。
-N /PATH/TO/SCRIPT 进程被杀死后执行脚本。
-g 杀死整个进程组。
-d, --debug 启用调试信息。
-v 显示版本信息并退出。
-r INTERVAL 内存报告间隔(以秒计,默认 1),设为 0 可禁用。
-p 设置 EarlyOOM 的 niceness 为 -20 和 oom_score_adj 为 -100。
--ignore-root-user 不杀死 root 用户的进程。
--sort-by-rss 按 RSS 大小选择进程而非 oom_score。
--prefer REGEX 优先杀死符合正则表达式的进程。
--avoid REGEX 避免杀死符合正则表达式的进程。
--ignore REGEX 忽略符合正则表达式的进程。
--dryrun 干跑模式(不杀死任何进程)。
--syslog 使用 syslog 记录日志。
-h, --help 显示帮助信息。
earlyoom
的命令行使用非常直观,可以通过不同的参数来配置它的行为。
注意事项:以上命令中正则表达式参数需要使用进程的comm
名称
--prefer
、--avoid
和--ignore
参数中使用的正则表达式需要根据进程名称的前 15 个字节进行匹配,因为comm
名称字段最大长度为 15 字节,超过部分会被截断。- 使用
--ignore
参数时需要特别小心,因为忽略某些关键进程可能会导致其他进程被杀死,从而影响系统的正常运行。
相关阅读:什么是进程的 comm 名称?Linux 进程 comm 名称详解
earlyoom 常用命令行使用示例
earlyoom
是一个内存管理工具,它可以在系统内存和交换空间低于设定阈值时提前杀死进程。以下是一些常用的命令行使用示例:
基本使用
earlyoom
使用默认配置,设置内存和交换空间阈值为 10%。当内存和交换空间都低于 10% 时,
earlyoom
会发送SIGTERM
,如果继续低于阈值,则发送SIGKILL
。自定义内存和交换空间阈值
earlyoom -m 20,10 -s 15,7
设置可用内存阈值为 20%,当内存低于 20% 时发送
SIGTERM
,低于 10% 时发送SIGKILL
。同时,设置交换空间阈值为 15%,低于 15% 时发送SIGTERM
,低于 7% 时发送SIGKILL
。指定内存和交换空间的绝对值
earlyoom -M 1048576,524288 -S 512000,256000
设置内存阈值为 1 GiB (1048576 KiB),低于此值时发送
SIGTERM
,低于 512 MiB (524288 KiB) 时发送SIGKILL
。交换空间阈值为 500 MiB (512000 KiB),低于此值时发送SIGTERM
,低于 250 MiB (256000 KiB) 时发送SIGKILL
。启用调试模式
earlyoom -d
启用调试信息输出,帮助排查问题。
启用通知
earlyoom -n
启用通过 D-Bus 发送通知。需要
systembus-notify
工具运行在用户会话中,以显示通知。执行脚本
earlyoom -N /path/to/script.sh
在每次进程被杀死时执行指定的脚本。脚本可以获取被杀死进程的相关信息,如 PID、进程名、命令行等。
增加优先级
earlyoom -p
增加
earlyoom
的优先级,将其niceness
设置为 -20,并将oom_score_adj
设置为 -100。需要通过系统服务配置来达到相同效果。模拟运行
earlyoom --dryrun
模拟运行
earlyoom
,不实际杀死任何进程,用于测试配置是否正确。忽略某些进程
earlyoom --ignore '^gnome-shell$'
--ignore
参数用于完全忽略名称匹配指定正则表达式(REGEX)的进程。这意味着这些进程无论内存使用情况如何,都不会被earlyoom
杀死。使用此选项时需要谨慎,因为忽略某些进程可能会导致其他进程被优先选择进行杀死,从而影响系统的稳定性。优先杀死某些进程
earlyoom --prefer '^Isolated Web Co$'
--prefer
参数用于优先杀死名称匹配指定正则表达式(REGEX)的进程。当某个进程的名称与给定的正则表达式匹配时,会在其oom_score
中增加 300 分,这使得该进程更有可能被优先选择进行杀死。避免杀死某进程
```sh earlyoom --avoid '^gunicorn$' ```
--avoid
参数用于避免杀死名称匹配指定正则表达式(REGEX)的进程。当某个进程的名称与给定的正则表达式匹配时,会在其oom_score
中减少 300 分,这使得该进程不太可能被选择进行杀死。
earlyoom 退出状态码
- 0: 成功执行。
- 1: 其他错误 - 检查错误消息以获取详细信息。
- 2: 开关冲突 - 使用了不兼容的选项。
- 4: 无法切换到
/proc
目录。 - 5: 无法打开
/proc
目录。 - 7: 无法打开
/proc/sysrq-trigger
。 - 13: 未知选项 - 传递了无效的选项。
- 14: 其他选项的参数错误。
- 15: 内存阈值参数错误。
- 16: 交换空间阈值参数错误。
- 102: 无法打开
/proc/meminfo
文件。 - 103: 无法读取
/proc/meminfo
文件。 - 104:
/proc/meminfo
文件中找不到特定条目。 - 105: 解析
/proc/meminfo
文件内容时转换数字失败。
配置文件
如果你将 earlyoom
作为系统服务运行,可以通过 /etc/default/earlyoom
文件调整其配置。例如:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
修改配置文件后,重新启动服务以应用更改:
systemctl restart earlyoom
测试 earlyoom
可以通过制造内存泄漏(切记不要在生产环境测试)来测试 earlyoom
的功能:
tail /dev/zero
查看日志
如果 EarlyOOM 作为 systemd 服务运行,可以通过以下命令查看最近的日志:
systemctl status earlyoom
或者查看详细日志:
sudo journalctl -u earlyoom -g "(sending|killing)" --since today
示例输出:
8月 05 00:53:43 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1389844 uid 0 "Isolated Web Co": badn>
8月 05 02:25:59 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1419894 uid 0 "Isolated Web Co": badn>
8月 05 03:52:30 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1448534 uid 0 "Isolated Web Co": badn>
8月 05 05:18:24 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1476938 uid 0 "Isolated Web Co": badn>
8月 05 06:48:10 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1505535 uid 0 "Isolated Web Co": badn>
8月 05 08:13:19 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1535267 uid 0 "Isolated Web Co": badn>
8月 05 09:40:01 32.3.18.8 earlyoom[3147772]: sending SIGTERM to process 1563244 uid 0 "Isolated Web Co": badn>
8月 05 10:32:45 32.3.18.8 earlyoom[1609353]: Will avoid killing process names that match regex '(init|sshd|su>
8月 05 10:32:45 32.3.18.8 earlyoom[1609353]: sending SIGTERM when mem <= 10.00% and swap <= 10.00%,
启用通知
从 1.6 版本开始,earlyoom
可以通过 d-bus 发送通知。需要启用 -n
选项,并运行 systembus-notify。
此外,earlyoom
可以在每次终止进程后执行脚本,使用 EARLYOOM_PID
、EARLYOOM_UID
和 EARLYOOM_NAME
环境变量提供进程信息。使用 -N /path/to/script
启用此功能。
发送通知到企业微信示例脚本:
#!/bin/bash
# 企业微信 webhook 地址
WEBHOOK_URL='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx'
# 生成通知内容
CONTENT="进程被EarlyOOM杀死\n\n"
CONTENT+="PID: $EARLYOOM_PID\n"
CONTENT+="进程名: $EARLYOOM_NAME\n"
CONTENT+="命令行: $EARLYOOM_CMDLINE\n"
CONTENT+="UID: $EARLYOOM_UID"
# 发送通知
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{
\"msgtype\": \"text\",
\"text\": {
\"content\": \"$CONTENT\"
}
}"
结论
earlyoom
是一个简单而有效的工具,可以帮助 Linux 用户避免由于内存不足而导致的系统无响应问题。通过提前检测和终止高内存占用的进程,earlyoom
保持系统的稳定性和响应速度。如果你经常遇到系统内存不足的问题,推荐试试 earlyoom
。