一般に、oom-killer は Linux ユーザーの間で評判が悪いです。これが、他に選択肢がまったくない場合にのみ Linux がそれを呼び出す理由の 1 つである可能性があります。最終的にプロセスを強制終了する前に、デスクトップ環境を交換し、ページ全体のキャッシュを削除し、すべてのバッファを空にします。少なくとも、そうなると私は思います。応答しないシステムの前に座ってそれを待つほどの忍耐力はまだありません。
このため、私や他の人々は、oom-killer が reddit r/linux、superuser.com、unix.stackexchange.com に早期に介入するように設定できないか疑問に思いました。
結局のところ、いいえ、それはできません。少なくともカーネル内の oom-killer を使用します。しかし、ユーザー空間では、やりたいことは何でもできます。
アーリールームはシンプルかつ堅牢でありたいと考えています。依存関係のない純粋な C で書かれています。広範なテスト スイート (単体テストおよび統合テスト) は Go で書かれています。
Earlyoom は、使用可能なメモリの量と空きスワップを 1 秒あたり最大 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
から値を取得できます。
利用可能なメモリと空きスワップの両方が、ユーザー空間プロセスで利用可能な総メモリ (= 合計共有) の 10% を下回ると、カーネルの判断で最も多くのメモリを使用しているプロセスにSIGTERM
シグナルが送信されます ( /proc/*/oom_score
)。
nohang は、earlyoom と同様のプロジェクトで、Python で書かれ、追加の機能と構成オプションを備えています。
facebooks の圧力ストール情報 (psi) カーネル パッチとそれに付随する oomd ユーザースペース ヘルパー。パッチは Linux 4.20 にマージされます。
Earlyoom は、次の理由によりecho f > /proc/sysrq-trigger
使用しません。
一部のカーネル バージョン (v4.0.5 でテスト済み) では、カーネル oom キラーを手動でトリガーしてもまったく機能しません。つまり、一部のグラフィックス メモリ (すぐに再び割り当てられる) を解放するだけで、実際にプロセスを強制終了することはありません。私のマシン (Intel 統合グラフィックス) でこれがどのように見えるかをここで確認できます。
この問題は Linux v5.17 (コミット f530243a) で修正されました。
Linux カーネルと同様に、earlyoom は/proc/*/oom_score
読み取ることで被害者を見つけます。
約2 MiB
( VmRSS
) ですが、プライベート メモリ ( RssAnon
) は220 kiB
のみです。残りは、他のプロセスと共有される libc ライブラリ ( RssFile
) です。メモリ不足の状況でも Earlyoom の速度が低下しないように、 mlockall()
使用してすべてのメモリがロックされます。
自分でコンパイルするのは簡単です。
git clone https://github.com/rfjakob/earlyoom.gitcd Earlyoom 作る
オプション: 統合されたセルフテストを実行します。
テストを行う
Earlyoom をサービスとして登録すると、自動的に開始されます。
sudo make install # systemdsudo make install-initscript # non-systemd
SELinux が無効になっているシステム (Ubuntu 19.04、Debian 9 ...) の場合、コンテキストの設定の失敗を報告する chcon 警告は無視しても安全であることに注意してください。
Debian 10 以降および Ubuntu 18.04 以降には、Debian パッケージがあります。
sudo apt installearlyoom
Fedora および EPEL を搭載した RHEL 8 には、Fedora パッケージがあります。
sudo dnf 早期インストール sudo systemctl Enable --now Earlyoom
Arch Linux の場合は、Arch Linux パッケージがあります。
sudo パックマン -S アーリールーム sudo systemctl Enable --now 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%) [...]
値が最小値を下回ると、再び最小値を超えるまでプロセスは強制終了されます。すべてのアクションは標準エラー出力に記録されます。 Earlyoom を systemd サービスとして実行している場合は、次を使用して最後の 10 行を表示できます。
systemctl ステータスが早いです
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
を渡します。
警告: ドライラン モードの場合、スクリプトは立て続けに実行されます。何らかのレート制限が実装されていることを確認してください。
コマンドライン フラグ--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 が早めに再起動します
この設定ファイルは、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 経由で受け付けます。特に喜んでお受けいたします
ユースケースレポートとフィードバック
procps_pids_select() は何らかの理由で常に /proc/$pid/status を解析するため、procps/libproc2 は使用しません。これは比較的高価なので、必要ありません。
v1.8.2、2024-05-07
process_mrelease
許可されたシステムコールに追加 (コミット)
IPAddressDeny
構文を修正 (コミット)
-p
(コミット) を許可する
earlyoom.service
systemd ユニットファイルの修正
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 を強制終了するプロセスが選択されます。最大の oom_score ではなく最大の RSS に設定されます。
Gitlab CI テストスイートは、Amazon Linux 2 および Oracle Linux 7 でも実行できるようになりました。
v1.7、2022-03-05
-N
フラグを追加して、プロセスが強制終了されるたびにスクリプトを実行します (コミット、マニュアルページセクション)
-g
フラグを追加してプロセス グループ全体を強制終了します (#247)
-i
フラグを削除します (互換性のために無視されます)。Linux カーネル 5.9 以降では正しく動作しません (#234)
強化: 起動時にアンビエント機能を削除 (#234)
v1.6.2、2020-10-14
被害者を殺害する前にメモリ状況を再確認します (コミット)
決して自分自身を終了させないでください (#205)
/proc/meminfo 変換エラー時のバッファのダンプ (#214)
1.6.1、2020-07-07
dbus-send ゾンビプロセスをクリーンアップ (#200)
oom_score_adj=-1000 (210) でプロセスをスキップ
1.6、2020-04-11
-n
/ -N
で新しいロジックが有効になりました
作業に関する通知を行うには、GUI セッションで systembus-notify を実行する必要があります。
古いnotify-send
GUI 通知ロジックをdbus-send
/ systembus-notify に置き換えます (#183)
Hidepid でマウントされた/proc
適切に処理する (問題 #184)
v1.5、2020-03-22
-p
: oom_score_adj を-1000
ではなく-100
に設定します (#170)
-M
と-m
、および-S
と-s
両方の使用を許可します。低い方の値 (パーセンテージに変換) が使用されます。
earlyoom.default
のメモリレポート間隔を 1 分ではなく 1 時間に設定します (#177)
v1.4、2020-03-01
可能な場合はブロックローカル変数を使用する
PATH_LEN を導入して、いくつかのハードコードされたバッファ長を置き換えます
プロセス属性の遅延読み込みにより、犠牲者選択ロジックを 50% 高速化
pid と名前に加えて、強制終了されたプロセスのユーザー ID uid
ログに記録します。
デバッグログをライトグレーで表示
コードのクリーンアップ
テストスイートを展開する ( make test
)
利用可能な場合はcppcheck
実行します
単体テストベンチマークを追加します ( make bench
)
systemd ユニットファイルearlyoom.service
の root 権限を削除します。
v1.3.1、2020-02-27
大量の RAM を搭載したシステムでの偽のテストスイートの障害を修正 (問題 #156)
v1.3、2019-05-26
SIGTERM 制限 < SIGKILL 制限の場合、致命的なエラーで終了しない
ゼロ SIGKILL 制限を許可する
これにより、earlyoom が 1 つで十分なときに複数のプロセスを強制終了することがある問題が修正されます (問題 #121)
シグナル送信時にプロセスが実際に終了するまで待機する
SIGTERM と SIGKILL で受け入れる制限をより自由にします (問題 #97)
起動出力を再フォーマットして、swap と mem の両方が制限値以下でなければならないことを明確にします。
Notice_all_users.py ヘルパー スクリプトを追加
CODE_OF_CONDUCT.md (貢献者規約 1.4) を追加 (#102)
ログ出力で切り詰められる可能性がある UTF8 アプリ名を修正 (#110)
v1.2、2018-10-28
CPU 使用率をさらに下げるために、適応スリープ時間 (= 適応ポーリング レート) を実装します (課題 #61)
カーネル oom-killer を使用するオプションを削除 ( -k
、現在は互換性のために無視されています) (問題 #80)
Earlyoom の開始後にスワップが追加または削除される場合を適切に処理します (問題 62、コミット)
段階的 Kill の実装: 最初に SIGTERM、次に SIGKILL、設定可能な制限付き (問題 #67)
v1.1、2018-07-07
GUI 通知によるシェルコードインジェクションの可能性を修正 (コミット)
プロセスの強制終了に失敗した場合は、10 秒ではなく 1 秒だけスリープします (問題 #74)
強制終了の前ではなく、終了後にGUI 通知を送信する (問題 #73)
-h
に加えて--help
も受け入れます
ログおよび強制終了通知内の間違ったプロセス名を修正しました (コミット 1、コミット 2、問題 #52、問題 #65、問題 #194)
-S
(コミット) によるゼロ除算の可能性を修正
v1.0、2018-01-28
--prefer
および--avoid
オプションを追加しました (@TomJohnZ)
GUI 通知のサポートを追加し、オプション-n
および-N
を追加します。
v0.12: -M
および-S
オプションを追加 (@nailgun); man ページを追加し、Makefile をパラメータ化します (@yangfl)
v0.11: get_entry_fatal の未定義の動作を修正 (リターン、コミットの欠落)
v0.10: パッケージ化を容易にするために Makefile の VERSION 変数をオーバーライドできるようにし、 -v
コマンドライン オプションを追加します
v0.9: すべてのプロセスの oom_score が 0 の場合、VmRss を使用して被害者を見つける
v0.8: カーネルが MemAvailable を提供しない場合は推測値を使用する
v0.7: VmRSS の代わりに oom_score で被害者を選択し、オプション-i
と-d
を追加
v0.6: コマンドラインオプション-m
、 -s
、 -k
を追加
v0.5: スワップサポートを追加
v0.4: SysV init スクリプトを追加 (@joeytwiddle に感謝)、 /proc/meminfo
から新しいMemAvailable
を使用 (Linux 3.14 以降、コミットが必要)
v0.2: systemd ユニットファイルを追加
v0.1: 初期リリース