LinuxのOOM Killerでプロセスが強制終了する原因と対処法|dmesgで確認してoom_score_adjで優先度を設定する方法

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, Linuxトラブルシューティング > LinuxのOOM Killerでプロセスが強制終了する原因と対処法|dmesgで確認してoom_score_adjで優先度を設定する方法
「Webサーバーが正常に動いているはずなのに、突然Apacheプロセスが消えた」「cronジョブが途中で終わるのにエラーログに何も記録されない」

こういったケースで真っ先に疑うべきなのが、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 を追記して永続化する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜプロセスが突然終了するのか

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

OOM Killerが発動していた場合、以下のような出力が記録されている:

# 実機出力(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

「javaプロセス(PID:8421)がscore:892でKillされた」と読み取れる。scoreが高いほどKill対象として選ばれやすく、0~1000の範囲で算出される。

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

実行例(RHEL 9.4 / 4GB RAM):

# スコアの高いプロセス TOP10 892 8421 java 345 7234 mysqld 123 5678 nginx 98 4321 httpd 12 987 sshd

この例ではjavaプロセスのスコアが飛び抜けて高く、メモリ不足が発生すれば真っ先にKillされる状況だ。

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

この方法はプロセスやサーバーの再起動でリセットされる点に注意すること。常駐プロセスへの適用には次のsystemd永続設定を使うのが鉄則だ。

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

実行例(RHEL 9.4):

# 確認結果 -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

実行例(RHEL 9.4 / 4GB RAM / OOM Killer発動前の典型的な状態):

# 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

Swap使用率が90%を超えている状態はOOM Killer発動寸前のサインだ。スワップの設計と拡張手順については「Linuxサーバーのスワップ領域を設計・拡張する方法」を参照してほしい。

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

sarコマンドでメモリ使用率の時系列変化を継続的に監視する方法は「sarコマンドでCPU・メモリの使用率履歴を確認する方法」が詳しい。

「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"

実行例(cgroupメモリ制限なしの場合):

# 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"
OOM Killerは「メモリ管理の失敗」ではなく「システムを守るための最終手段」だ。まずdmesgでKillされたプロセスとスコアを特定し、重要プロセスにはoom_score_adj=-1000を設定して保護する。その上でfree -hやスワップの使用率を定期的に監視しながら、根本的な対策(スワップ増強・アプリのメモリ最適化)につなげていくのが実務での正しい手順だ。

サーバーが急に重くなるケース全般の切り分けは「Linuxサーバーが急に重くなった時の原因切り分け手順」も参考にしてほしい。

OOM Killerの調査ができたら、次は「なぜこうなるのか」をLinux設計の視点で理解する

oom_score_adjで重要プロセスを守ることができたら、次のステップはカーネルのメモリ管理の仕組みそのものを理解することです。freeコマンドの読み方・スワップの設計・cgroup v2のメモリ制限まで体系的に把握することで、OOMが起きる前に予防できる設計力が身につきます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。