こういったケースで真っ先に疑うべきなのが、LinuxカーネルのOOM Killer(アウト・オブ・メモリ・キラー)だ。メモリが枯渇したとき、カーネルがシステム全体のクラッシュを防ぐために特定のプロセスを強制終了する仕組みで、実行時に通常のエラーを返さないため、カーネルログを調べなければ原因に気づかないことが多い。
この記事では、OOM Killerが発動したかどうかをログで確認する方法から、
oom_score_adjを使って重要プロセスをKill対象から除外する恒久設定まで、RHEL 9.4 / Rocky Linux 9の実機出力をもとに解説する。この記事のポイント
・OOM Killerの発動は dmesg | grep -i oom で即確認できる
・Kill対象はoom_scoreが高いプロセス(/proc/PID/oom_scoreで確認)
・oom_score_adjを-1000にするとそのプロセスはKill対象から外れる
・systemdサービスはユニットに OOMScoreAdjust=-1000 を追記して永続化する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜプロセスが突然終了するのか
OOM Killerはカーネルが実装する「最後の砦」だ。物理メモリとスワップ領域の両方が使い切られると、カーネルはシステム全体のパニックに至る前に、最もメモリを占有しているプロセスをスコアで選び出してKillする。この動作は意図的な設計であり、OOM Killerが動くこと自体は正常だ。問題はKill対象として重要なサービスが選ばれてしまったとき。Apache・MySQL・Javaアプリのようにメモリを多く使うサービスほどスコアが高くなりやすく、対策なしでは「突然死」のリスクを抱えたまま運用することになる。
OOM Killerが問題になりやすい環境:
・バッチ処理やJavaアプリが一時的に大量のメモリを消費する環境
・物理メモリが2GB以下のVPSやコンテナ環境
・メモリリークが疑われる長時間稼働のプロセスが存在する場合
OOM Killerが動いたかをログで確認する
1. dmesgで確認する
カーネルのリングバッファに記録される。起動後にOOM Killerが動いた場合はここに残る。# OOM Killer のログを確認する dmesg | grep -i "out of memory" # または "oom" でフィルタする(大文字小文字を区別しない) dmesg | grep -i oom
# 実機出力(RHEL 9.4 / hostname: ap01.example.local) [4523867.123456] Out of memory: Kill process 8421 (java) score 892 or sacrifice child [4523867.134567] Killed process 8421 (java) total-vm:4194304kB, anon-rss:3829760kB, file-rss:0kB [4523867.145678] oom_kill_process: Out of memory: Kill process 8421 (java) score 892
2. journalctlで確認する
再起動をまたいだ過去のログや詳細な時刻情報はjournalctlで確認できる。# カーネルメッセージからOOM関連を抽出する journalctl -k | grep -i "out of memory" # 前回起動時のログも確認する(-b -1 で前回boot) journalctl -k -b -1 | grep -i oom # 特定の日時以降で絞り込む journalctl --since "2026-07-01 00:00:00" | grep -i "out of memory"
どのプロセスがKill対象になるか
1. oom_scoreを確認する
稼働中の全プロセスには/proc/PID/oom_scoreというファイルがあり、OOM Killerはこのスコアを参照して対象を選択する。# 特定プロセスのスコアを確認する(例: httpd) PID=$(pidof httpd | awk '{print $1}') cat /proc/$PID/oom_score # 全プロセスをスコア降順で一覧表示する for pid in $(ls /proc | grep -E '^[0-9]+$'); do score=$(cat /proc/$pid/oom_score 2>/dev/null) comm=$(cat /proc/$pid/comm 2>/dev/null) [ -n "$score" ] && echo "$score $pid $comm" done | sort -rn | head -10
# スコアの高いプロセス TOP10 892 8421 java 345 7234 mysqld 123 5678 nginx 98 4321 httpd 12 987 sshd
2. oom_scoreの算出ロジック
oom_scoreは主に次の要素で増加する:・プロセスが占有している物理メモリ量(最大の要因)
・子プロセスのメモリ合算値
・スーパーユーザー(root)プロセスはごくわずかに低く算出される
「スコアが高い=メモリを多く使っている=Kill対象になりやすい」という設計だ。ApacheやMySQLのように本来重要なプロセスほどスコアが高くなりやすく、何も設定しなければ障害発生時に最初にKillされるリスクがある。
重要プロセスをKillから守るoom_score_adjの設定
oom_score_adj(-1000 ~ +1000)をプロセスに設定することで、最終的なKillスコアを調整できる。・-1000 に設定するとスコアが実質ゼロ以下になり、OOM Killerの選択対象から外れる
・+1000 に設定するとスコアが最大化され、優先的にKillされる
・デフォルトは 0(oom_scoreの計算値がそのまま使われる)
1. 一時的に設定する(プロセス再起動でリセット)
# プロセスのPIDを特定する(例: httpd) PID=$(pidof httpd | awk '{print $1}') echo "対象PID: $PID" # 現在のoom_score_adjを確認する cat /proc/$PID/oom_score_adj # -1000を設定してKill対象から除外する(root権限が必要) echo -1000 > /proc/$PID/oom_score_adj # 設定を確認する cat /proc/$PID/oom_score_adj
# 変更前 0 # 変更後 -1000
2. systemdサービスに永続設定する
systemdで管理されているサービスには、ユニットファイルのオーバーライドで設定を永続化するのが正しいやり方だ。既存のユニットファイルを直接編集するのではなく、/etc/systemd/system/サービス名.service.d/配下にオーバーライドファイルを作成する。# オーバーライドディレクトリを作成する(例: httpd) mkdir -p /etc/systemd/system/httpd.service.d/ # 設定ファイルを作成する(vi で編集する) vi /etc/systemd/system/httpd.service.d/oom.conf
[Service] OOMScoreAdjust=-1000
# systemdデーモンをリロードしてサービスを再起動する systemctl daemon-reload systemctl restart httpd # PIDを確認してoom_score_adjを検証する PID=$(pidof httpd | awk '{print $1}') cat /proc/$PID/oom_score_adj
# 確認結果 -1000
3. systemd以外のプロセスへの設定
cronや自作の常駐スクリプトには、起動スクリプトの先頭で設定する方法が現実的だ。$$はシェルスクリプト自身のPIDを指す。#!/bin/bash # スクリプト起動直後に自プロセスのoom_score_adjを設定する echo -1000 > /proc/$$/oom_score_adj echo "oom_score_adjを設定: $(cat /proc/$$/oom_score_adj)" # ここから本来の処理を開始する
OOM発生を防ぐための運用設計
oom_score_adjによる優先度の調整は「重要プロセスを守る」対症療法だ。根本的にはメモリ不足そのものを解消する必要がある。1. メモリとスワップの使用状況を把握する
# メモリとスワップの使用状況を確認する free -h # vm.overcommit_memoryの設定を確認する # (0=ヒューリスティック, 1=常に許可, 2=制限あり) cat /proc/sys/vm/overcommit_memory
# free -h の出力 total used free shared buff/cache available Mem: 3.7Gi 3.1Gi 124Mi 38Mi 512Mi 442Mi Swap: 2.0Gi 1.8Gi 212Mi # vm.overcommit_memory 0
2. vm.swappinessでメモリ利用の傾向を調整する
vm.swappiness(0 ~ 100、デフォルト 60)は、カーネルがどの程度積極的にメモリをスワップに追い出すかを制御するパラメータだ。# 現在のswappinessを確認する cat /proc/sys/vm/swappiness # データベースサーバーの場合は低めに設定する # /etc/sysctl.confに追記して再起動後も維持する echo "vm.swappiness=10" >> /etc/sysctl.conf sysctl -p
「oom_score_adj -1000を設定したのにKillされた」場合のトラブルシュート
設定後もプロセスが突然終了する場合は、以下を順番に確認する。・設定の反映漏れ:
systemctl daemon-reloadの実行後にサービスを再起動したか確認する。複数のhttpdワーカープロセスが動いている場合、親プロセスのPIDにしか設定できていないケースがある・cgroup OOMとの混同:コンテナやcgroup v2環境でメモリ上限を設定している場合、OOM Killerとは別の「cgroup OOM」が発動する。この場合は/proc/PID/oom_score_adjではなくcgroupのメモリ制限の見直しが必要
・SIGKILL(手動Kill)との混同:監視ツールやwatchdogスクリプトが意図せずkillを送っていないかを確認する
# systemdサービスのcgroupメモリ制限を確認する systemctl show httpd | grep -i memory # cgroup OOMの発動ログを確認する journalctl | grep -i "oom-kill\|memory.oom.group"
# systemctl show httpd の出力(メモリ制限なし) MemoryAccounting=no MemoryMax=infinity
MemoryMax=infinityであればcgroup側のメモリ制限は設定されていない。本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| OOM Killerの発動を確認する | dmesg | grep -i oom |
| 過去のOOMログを確認する | journalctl -k -b -1 | grep -i oom |
| プロセスのoom_scoreを確認する | cat /proc/PID/oom_score |
| Kill対象から除外する(一時) | echo -1000 > /proc/PID/oom_score_adj |
| systemdサービスに永続設定する | ユニットファイルに OOMScoreAdjust=-1000 |
| cgroup OOMを確認する | journalctl | grep -i "oom-kill" |
dmesgでKillされたプロセスとスコアを特定し、重要プロセスにはoom_score_adj=-1000を設定して保護する。その上でfree -hやスワップの使用率を定期的に監視しながら、根本的な対策(スワップ増強・アプリのメモリ最適化)につなげていくのが実務での正しい手順だ。サーバーが急に重くなるケース全般の切り分けは「Linuxサーバーが急に重くなった時の原因切り分け手順」も参考にしてほしい。
OOM Killerの調査ができたら、次は「なぜこうなるのか」をLinux設計の視点で理解する
oom_score_adjで重要プロセスを守ることができたら、次のステップはカーネルのメモリ管理の仕組みそのものを理解することです。freeコマンドの読み方・スワップの設計・cgroup v2のメモリ制限まで体系的に把握することで、OOMが起きる前に予防できる設計力が身につきます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Linuxのカーネルモジュールを管理する方法|lsmod・modprobeで確認・ロード・ブラックリスト設定と永続化
- この記事の属するカテゴリ:Linuxtips・Linuxトラブルシューティングへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます