🐧 Linux 総合学習プラットフォーム
プロセス監視/障害対応 ・ 中級

メモリ不足とOOM Killer

メモリが足りなくなると、Linuxはまずスワップに逃げて延命し、それでも足りなければカーネルがプロセスを強制終了して全滅を防ぎます。この仕組みをOOM Killerと呼びます。free の読み方、スワップの副作用、誰が・なぜ殺されたのかをログから読み解く手順を身につけると、突然アプリが落ちる障害にも慌てず対応できます。

「さっきまで動いていたアプリが、いつの間にか落ちている」――ログにエラーもなく、ただ消えている。これはメモリ不足が原因であることが多い障害だ。

CPUの過負荷なら重くなるだけで動き続けることが多いが、メモリはゼロになると話が変わる。空きが尽きると、カーネルは生き残りをかけてプロセスを殺しにかかる。この仕組みを知らないと、原因不明の突然死に見えてしまう。

🔗
たとえメモリ不足は満員電車に似ている。多少混んでも乗客(プロセス)はそこにいられるが、本当に定員オーバーになると駅員(カーネル)が誰かを強制的に降ろして安全を守る。降ろされる客を選ぶ基準があるように、OOM Killerにも選び方がある。

📉 free -h の読み方——本命は available

メモリの空き具合を見る基本コマンドが free -h だ。だが、この出力にはよくある誤読ポイントがある。

free -h を打つと total・used・free・shared・buff/cache・available という列が並ぶ。多くの初学者は free(空き)の数値が小さいと「メモリが足りない」と早合点してしまう。

free -h ……total 3.8Gi / used 1.2Gi / free 1.1Gi / buff/cache 1.5Gi / available 2.3Gi のように出る。見るべきは available で、free の小ささだけで慌てる必要はない。

buff/cache は、Linuxがディスクの読み書きを高速化するために空きメモリを一時的にキャッシュとして使っている分だ。これはアプリが必要とすればすぐに手放される、いわば「今は空いているので有効活用中」の領域である。

💡
ポイントbuff/cache は敵ではなく味方。アプリがメモリを要求すれば即座に解放されるキャッシュなので、free の値が小さくてもここが厚ければ実質的には余裕がある。

そのため本当に見るべきは available 列だ。これは「buff/cache を解放した場合も含めて、新しいプロセスがすぐに使える見込みのメモリ量」をカーネルが計算した値になる。available が小さくなってきたときこそ、本当の意味でメモリが逼迫している。

used 1.2Gifree 1.1Gibuff/cache 1.5Giavailable 2.3Gibuff/cache必要なら即解放される味方available が本命解放込みで使える実質量free の数値だけで慌てない。available を見る

逆に言えば、free の値がほぼゼロでも available が十分にあれば健全な状態だ。Linuxは空きメモリを遊ばせずキャッシュに回すのが標準動作なので、free が小さいこと自体は異常ではない。

🐌 スワップに逃げると、遅くなる

available も心もとなくなってくると、Linuxは次の手として スワップ(tbl-swap) を使う。物理メモリの中身の一部をディスク上の領域に一時退避し、空きを作る仕組みだ。

スワップのおかげで、多少のメモリ不足ならプロセスを殺さずに済む。だが代償は大きい。ディスクはRAMに比べて桁違いに遅く、スワップの読み書き(swap-in / swap-out)が頻発すると、体感速度が急激に悪化する。

つまずきスワップは「落ちるよりはマシ」な延命策であって、根本解決ではない。スワップが激しく動いている状態(スラッシング)は、実質的にはメモリ不足の障害が進行中と考えたほうがよい。

free -h の Swap 行の used が増え続けている、あるいは vmstat の si/so(swap-in/swap-out)の値が高止まりしているようなら、スワップに頼り切った危険な状態だと判断できる。

ここで気をつけたいのは、スワップが「あるだけで悪」というわけではないという点だ。ごく軽微な、めったに使わないメモリ領域が少しだけスワップへ追い出される程度なら、体感速度への影響はほとんどない。問題視すべきは、頻繁に読み書きが発生し続ける「スラッシング」状態のほうだ。

vmstat 1 を数十秒流して si/so の列を眺めると、スワップが一時的な現象か慢性的な現象かを見分けやすい。ときどき数値が出る程度なら様子見でよいが、継続的に高い値が出るなら要注意のサインだ。

☠ OOM Killer——最後の砦

スワップも使い切り、それでもメモリ要求に応えられなくなると、カーネルは最終手段に出る。これがOOM Killer(tbl-oom)だ。

OOM Killerは、システム全体がメモリ枯渇で完全に応答不能になる前に、いくつかのプロセスを選んで強制終了し、残りのシステムを生かそうとする仕組みだ。全滅を防ぐための、いわば緊急避難措置である。

🔗
たとえ満員の救命ボートで、これ以上乗せると沈むという瀬戸際に、船長が一部の荷物を海に投げ捨てて全員を沈没から守るような動きだ。荷物に選ばれたプロセスにとっては理不尽でも、全体を守るための判断になる。

どのプロセスを終了させるかは、カーネルが内部で計算する「OOMスコア」という指標にもとづいて決まる。多くのメモリを使っているプロセスほどスコアが高くなりやすく、優先的に狙われる傾向がある。逆に、OSの根幹を支える重要なプロセスにはスコアを下げる調整が入っており、めったなことでは狙われない設計になっている。

つまずきOOM Killerに殺されるプロセスは、必ずしも「悪さをしたプロセス」とは限らない。メモリを大量に使う設計のアプリが、たまたま最後の一押しになっただけで選ばれることもある。犯人探しは、殺された側だけでなく直前の全体の動きも含めて見る必要がある。

🔍 dmesg・journalctl -k で足跡を探す

アプリが原因不明に落ちたら、まずOOM Killerが動いていないかを疑い、ログで裏を取る。

カーネルのメッセージは dmesg か journalctl -k で見られる。ここに「Out of memory: Killed process」という文字列があれば、それがOOM Killerの実行記録だ。

dmesg | grep -i 'out of memory' ……カーネルメッセージから該当行を抜き出す。journalctl -k でも同じ系統のログを検索できる。
コツ落ちたのが最近ならログの後ろのほうにあるはずなので、dmesg | tail -n 50 のように末尾から見るのも早い。journalctl -k --since '-1 hour' のように時間で絞る手もある。

📖 誰が・なぜ殺されたかを読む

OOM Killerのログには手がかりが詰まっている。Killed process の行には、殺されたプロセスのPID・名前・使用メモリ量(total-vm や rss)が記録される。

Out of memory: Killed process 1834 (python3)total-vm:2100000kB, anon-rss:1850000kBPID / 名前誰が殺されたかtotal-vm/rssどれだけ食っていたか直前の全体状況なぜ枯渇したか

PIDと名前で「何が」殺されたかが分かり、total-vm・rss の値で「どれだけメモリを抱えていたか」が分かる。同じログの少し上には、殺害の判断に至った直前のメモリ使用状況も記録されていることが多く、なぜ枯渇に至ったのかの手がかりになる。

💡
ポイントOOM Killerのログは「誰が」「どれだけ食っていたか」「殺害直前の全体状況」の3点セットで読む。これで単発の暴走か、恒常的な不足かを見分けられる。

殺されたのが特定の1プロセスだけで、他は普段どおりなら、そのプロセスのメモリリークや一時的な負荷急増が疑わしい。逆に複数プロセスが順に殺されているなら、システム全体が慢性的にメモリ不足である可能性が高い。

🛠 対処——増設・swap・アプリ設定・cgroup

原因が読めたら、対処の選択肢はいくつかある。

根本的な解決は物理メモリの増設だが、すぐには対応できないことも多い。応急処置としてはスワップ領域を増やす方法がある。スワップは遅いが、突然のプロセス強制終了よりはましな場合が多い。

クラウド上の仮想マシンなどですぐにメモリを増設できない場合、swapfileと呼ばれる普通のファイルを一時的なスワップ領域として追加する手がよく使われる。ディスクに空きさえあれば、再起動せずにその場でメモリの逃げ場を増やせる、手軽な延命策になる。

アプリ側の設定でメモリ使用量の上限を絞る、キャッシュサイズを調整する、といった対処も有効だ。データベースやWebサーバーには、たいていメモリ使用量に関する設定項目がある。

より踏み込んだ対処が cgroup(コントロールグループ)によるメモリ制限だ。プロセスのグループごとにメモリ使用量の上限を割り当てておけば、あるアプリが暴走しても他のプロセスを巻き込まずに済む。コンテナ技術の多くもこの仕組みを利用している。

コツ大事なサービスには、あらかじめ「これくらいまでは使ってよい」という上限を決めておくと、1つの暴走が全体のOOM Killer発動を招く事態を防ぎやすい。

突然の落ち方に出会ったら、慌てず free -h で available を見て、dmesg や journalctl -k でOOM Killerの足跡を探す――この流れを押さえておけば、原因不明に見える障害も筋道立てて説明できるようになる。

この項目に出てくる用語

available(実質空きメモリ)あべいらぶる
buff/cacheの解放分も含めて新規プロセスがすぐ使える見込みのメモリ量。
cgroup(コントロールグループ)しーぐるーぷ
プロセスのグループごとにCPU・メモリなどの使用上限を割り当てるカーネル機能。

▶ 学習アプリでこの続きを学ぶ・演習する