oom-killer 在 Linux 用戶中通常名聲不佳。這可能是 Linux 僅在別無選擇時才調用它的部分原因。它將交換桌面環境,刪除整個頁面快取並清空每個緩衝區,然後最終殺死進程。至少我認為它會做到這一點。我還沒有足夠的耐心等待它,坐在一個沒有反應的系統前面。
這讓我和其他人想知道 oom-killer 是否可以配置為更早介入:reddit r/linux、superuser.com、unix.stackexchange.com。
事實證明,不,不能。至少使用核心中的 oom-killer。然而,在使用者空間,我們可以做任何我們想做的事情。
Earlyoom 希望簡單可靠。它是用純 C 語言編寫的,沒有依賴關係。廣泛的測試套件(單元測試和整合測試)是用 Go 編寫的。
Earlyoom 每秒最多檢查 10 次可用內存和可用交換空間(如果有大量可用內存,則頻率會降低)。預設情況下,如果兩者都低於 10%,它將殺死最大的進程(最高的oom_score
)。百分比值可透過命令列參數進行設定。
在下面的free -m
輸出中,可用記憶體為 2170 MiB,可用交換空間為 231 MiB。
total used free shared buff/cache available
Mem: 7842 4523 137 841 3182 2170
Swap: 1023 792 231
為什麼檢查“可用”內存而不是“空閒”內存?在一個健康的 Linux 系統上,「空閒」記憶體應該接近零,因為 Linux 使用所有可用的實體記憶體來快取磁碟存取。當記憶體需要用於其他用途時,可以隨時刪除這些快取。
「可用」記憶體說明了這一點。它匯總了所有未使用或可以立即釋放的記憶體。
請注意,您需要最新版本的free
版本和 Linux 核心 3.14+ 才能看到「可用」列。如果您有最新的內核,但free
版本較舊,則可以從grep MemAvailable /proc/meminfo
取得值。
當你的可用記憶體和空閒交換區都低於用戶空間進程可用總記憶體(=total-shared)的 10% 時,它將向核心認為使用最多記憶體的進程發送SIGTERM
訊號( /proc/*/oom_score
) 。
Earlyoom 不使用echo f > /proc/sysrq-trigger
因為:
在某些核心版本中(在 v4.0.5 上測試),手動觸發核心 oom Killer 根本不起作用。也就是說,它可能只會釋放一些圖形記憶體(將立即再次分配),而不會真正殺死任何進程。在這裡您可以看到它在我的機器(英特爾整合式顯示卡)上的樣子。
此問題已在 Linux v5.17 中修復(提交 f530243a)。
就像 Linux 核心一樣,earlyoom 透過讀取/proc/*/oom_score
來找到它的受害者。
大約2 MiB
( VmRSS
),儘管只有220 kiB
是私有記憶體 ( RssAnon
)。其餘的則是與其他行程共用的 libc 函式庫 ( RssFile
)。使用mlockall()
鎖定所有內存,以確保 Earlyoom 在內存不足的情況下不會減慢速度。
自己編譯很容易:
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
可選:運行整合自測試:
make test
透過將earlyoom註冊為服務來自動啟動earlyoom:
sudo make install # systemd
sudo make install-initscript # non-systemd
請注意,對於停用 SELinux 的系統(Ubuntu 19.04、Debian 9 ...),可以安全地忽略報告設定上下文失敗的 chcon 警告。
對於 Debian 10+ 和 Ubuntu 18.04+,有一個 Debian 軟體包:
sudo apt install earlyoom
對於 EPEL 的 Fedora 和 RHEL 8,有一個 Fedora 軟體包:
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
eearlyoom 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%)
[...]
如果該值降至最小值以下,則進程將被終止,直到再次高於最小值。每個操作都會記錄到 stderr。如果您將 Earlyoom 作為 systemd 服務運行,則可以使用以下命令查看最後 10 行
systemctl status earlyoom
為了查看earlyoom
實際效果,請建立/模擬記憶體洩漏並讓earlyoom
執行其操作:
tail /dev/zero
如果您在進程被earlyoom
終止後需要任何進一步的操作(例如發送電子郵件),您可以透過以下方式解析日誌:
sudo journalctl -u earlyoom | grep sending
上述測試指令( tail /dev/zero
)的範例輸出將如下所示:
Feb 20 10:59:34 debian earlyoom[10231]: sending SIGTERM to process 7378 uid 1000 "tail": oom_score 156, VmRSS 4962 MiB
對於舊版的
earlyoom
,請使用:sudo journalctl -u earlyoom | grep -iE "(sending|killing)"
從 1.6 版本開始,earlyoom 可以透過系統 d-bus 發送有關終止進程的通知。通過-n
來啟用它們。
要實際在 GUI 會話中查看通知,您需要以使用者身分執行 systembus-notify。
此外,earlyoom 可以為每個被殺死的進程執行一個腳本,透過EARLYOOM_PID
、 EARLYOOM_UID
和EARLYOOM_NAME
環境變數提供有關進程的資訊。透過-N /path/to/script
來啟用。
警告:在 dryrun 模式下,腳本將快速連續執行,確保您實作了某種速率限制。
命令列標誌--prefer
指定優先殺死進程;同樣, --avoid
指定避免殺死的進程。有關詳細信息,請參閱 https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex。
如果您將 Earlyoom 作為系統服務運行(透過 systemd 或 init.d),則可以透過/etc/default/earlyoom
中提供的檔案調整其配置。該文件已在註釋中包含一些範例,您可以使用它們根據支援的命令列選項建立自己的配置集,例如:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
調整文件後,只需重新啟動服務即可套用變更。例如,對於 systemd:
systemctl restart earlyoom
請注意,此設定檔對 systemd/init.d 以外的 Earlyoom 實例沒有影響。
earlyoom v1.8
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 %).
Note: both memory and swap must be below minimum for
earlyoom to act.
-M SIZE[,KILL_SIZE] set available memory minimum to SIZE KiB
-S SIZE[,KILL_SIZE] set free swap minimum to SIZE KiB
-n enable d-bus notifications
-N /PATH/TO/SCRIPT call script after oom kill
-g kill all processes within a process group
-d, --debug 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
-100
--ignore-root-user do not kill processes owned by root
--sort-by-rss find process with the largest rss (default oom_score)
--prefer REGEX prefer to kill processes matching REGEX
--avoid REGEX avoid killing processes matching REGEX
--ignore REGEX ignore processes matching REGEX
--dryrun dry run (do not kill any processes)
--syslog use syslog instead of std streams
-h, --help this help text
有關詳細信息,請參閱手冊頁。
歡迎透過 github 提交錯誤報告和拉取請求。特別是我很高興接受
v1.8.2, 2024-05-07
earlyoom.service
systemd 單元文件process_mrelease
加入到允許的系統呼叫(提交)IPAddressDeny
語法(提交)-p
(提交)v1.8.1, 2024-04-17
v1.8, 2024-04-15
user mem total
/ meminfo_t.UserMemTotal
並根據它計算 MemAvailablePercent (提交,手冊頁中的更多資訊)process_mrelease
(#266)NO_COLOR
(https://no-color.org/)--sort-by-rss
,謝謝@RanHuang!這將選擇一個進程來殺死 acc。使用最大的 RSS 而不是最大的 oom_score。v1.7, 2022-03-05
-N
標誌以在每次進程被終止時執行腳本(提交,手冊頁部分)-g
標誌來終止整個進程組 (#247)-i
標誌(為了相容性而忽略),它在 Linux 核心 5.9+ 上無法正常運作(#234)v1.6.2, 2020-10-14
1.6.1, 2020-07-07
1.6, 2020-04-11
dbus-send
/ systembus-notify 取代舊的notify-send
GUI 通知邏輯 (#183)-n
/ -N
現在啟用新邏輯/proc
(問題 #184)v1.5, 2020-03-22
-p
: 將 oom_score_adj 設為-100
而不是-1000
(#170)-M
和-m
以及-S
和-s
。將使用較低的值(轉換為百分比)。earlyoom.default
中的記憶體報告間隔設定為1小時而不是1分鐘(#177)v1.4, 2020-03-01
uid
make test
)cppcheck
make bench
)earlyoom.service
中的 root 權限v1.3.1, 2020-02-27
v1.3, 2019-05-26
v1.2, 2018-10-28
-k
,現在為了相容性而忽略)(問題#80)v1.1, 2018-07-07
-h
之外還接受--help
-S
修復可能被零除的情況(提交)v1.0, 2018-01-28
--prefer
和--avoid
選項 (@TomJohnZ)-n
和-N
v0.12:新增-M
和-S
選項(@nailgun);新增手冊頁,參數化 Makefile (@yangfl)
v0.11:修正 get_entry_fatal 中未定義的行為(缺少回傳、提交)
v0.10:允許覆蓋Makefile的VERSION變數以使打包更容易,新增-v
命令列選項
v0.9:如果所有行程的oom_score為0,則使用VmRss找出受害者
v0.8:如果核心不提供 MemAvailable,則使用猜測
v0.7:透過 oom_score 而不是 VmRSS 選擇受害者,新增選項-i
和-d
v0.6: 新增命令列選項-m
, -s
, -k
v0.5:新增交換支持
v0.4:新增 SysV 初始化腳本(感謝 @joeytwiddle),使用/proc/meminfo
中的新MemAvailable
(需要 Linux 3.14+,提交)
v0.2:新增systemd單元文件
v0.1:初始版本