Linuxメモリ不足を迅速に特定・解決する実践的な調査手法

Linuxサーバーのメモリ不足に直面した際、原因を素早く特定し対処することは運用の要です。本記事では、freepstopなどの標準ツールを活用した診断方法と、メモリリーク検出、スワップ調整、プロセス制御までの実践的な手順を解説します。これらの技法を習得すれば、本番環境での障害対応時間を大幅に短縮できます。

Linuxメモリ不足の兆候を見抜く

メモリ不足の初期兆候を見逃さないことが重要です。以下のシグナルが現れたら、本格的な調査を始めましょう。

まず確認すべき3つの兆候

  • アプリケーションの処理速度が急激に低下
  • OOM Killer(Out Of Memory Killer)によるプロセス強制終了
  • スワップ領域への頻繁なアクセス(ディスク I/O が増加)

これらの症状が見られたら、次のステップで詳細な状況把握に進みます。

メモリ使用状況を素早く診断する

free コマンドでメモリ全体を把握

freeコマンドはメモリ使用状況を最速で確認できる基本ツールです。

free -h

出力例:

              total        used        free      shared  buff/cache   available
Mem:           15Gi       9.2Gi       1.1Gi       256Mi        4.8Gi       5.2Gi
Swap:          4.0Gi       2.1Gi       1.9Gi

ここで重要なのはavailableカラムです。これはOSが確保できる実質的な空き容量を示し、freeより正確です。

# メモリ状況を1秒間隔で継続監視
free -h -s 1

top コマンドでプロセスレベルの消費メモリを追跡

topコマンドで、どのプロセスがメモリを圧迫しているかを特定します。

top -b -n 1 | head -20

-bはバッチモード、-n 1は1回だけ実行してスクリプトから利用できます。

メモリ使用量でソートして表示する場合:

# 対話モード内で 'M' を入力、またはコマンドで直接指定
top -b -n 1 -o %MEM

ps コマンドで詳細な消費メモリ情報を取得

複数プロセスのメモリ消費をCSV形式で一覧化することで、分析が容易になります。

ps aux --sort=-%mem | head -20

より詳細な情報が必要な場合:

ps -eo pid,user,vsz,rss,comm --sort=-rss | head -20
  • VSZ(Virtual Memory Size):プロセスが確保している仮想メモリ総量
  • RSS(Resident Set Size):物理メモリに実際に収まっている部分

メモリリークを検出・分析する

特定プロセスのメモリ増加傾向を追跡

同じプロセスがメモリを増やし続ける場合、メモリリークの可能性があります。

#!/bin/bash
# 特定PIDのメモリ使用量を5分間、30秒ごとにログ記録
TARGET_PID=$1
INTERVAL=30
DURATION=300  # 5分

echo "timestamp,rss_mb" > memory_log.csv
END=$(($(date +%s) + DURATION))

while [ $(date +%s) -lt $END ]; do
  TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
  RSS_KB=$(ps -p $TARGET_PID -o rss= | awk '{print $1}')
  RSS_MB=$((RSS_KB / 1024))
  echo "$TIMESTAMP,$RSS_MB" >> memory_log.csv
  sleep $INTERVAL
done

このログをグラフ化すれば、メモリリークの有無が視覚的に判定できます。

ハマりポイント:ページキャッシュとの混同

buff/cache欄が大きい場合、これはファイルシステムキャッシュであり、アプリケーションメモリではありません。ほぼ自動で解放されるため、availableの数字を優先して判断してください。

メモリ不足への即座の対処法

1. 不要なプロセスを停止

開発環境に残ったテストプロセスやバックグラウンドサービスを特定して終了します。

# メモリ消費が大きい順に表示
ps aux --sort=-%mem | grep -v grep | awk 'NR>1 {printf "%d %s\n", NR-1, $0}' | head -10

# 特定プロセスを安全に終了(SIGTERM送信)
kill -15 [PID]

# 応答しない場合のみ強制終了(SIGKILL)
kill -9 [PID]

2. スワップ領域を活用(一時的な対応)

スワップはメモリ不足時のセーフティネットですが、ディスク I/O が増加するため根本解決ではありません。

# 現在のスワップ使用状況を確認
swapon -s

# 追加スワップファイルを作成(2GB分)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 永続化:/etc/fstabに追加
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab

3. OOM Killer のログを確認

カーネルがプロセスを強制終了した痕跡はシステムログに記録されます。

# OOM Killer のログを確認
grep "Out of memory" /var/log/kern.log

# dmesgでも確認可能
dmesg | tail -30 | grep "oom-kill"

4. アプリケーション側でメモリ制限を設定

Javaアプリケーションの場合、ヒープサイズを明示的に制限することで、予期しないメモリ枯渇を防げます。

# Javaプロセスのヒープを最大4GBに制限
java -Xmx4G -Xms2G -jar application.jar

# Pythonプロセスにメモリ制限を適用(ulimit経由)
ulimit -v 8388608  # 8GB制限
python3 heavy_app.py

根本的な解決策と予防措置

メモリリークの本格的な調査

メモリ増加が継続する場合、プロファイリングツールで詳細分析が必要です。

  • Pythonアプリmemory_profilertracemallocモジュール
  • Javaアプリjmapjhat、Eclipse Memory Analyzer
  • C/C++アプリvalgrindAddressSanitizer

ハマりポイント:本番環境でのプロファイリング

プロファイリングツールはオーバーヘッドが大きいため、本番環境では軽量なログ出力に留め、ステージング環境で詳細調査することを推奨します。

長期的な対策

  • サーバーメモリの増設検討:スケールアップが必要か、スケールアウト(複数サーバー化)の方が効率的か判断
  • 監視アラート設定:メモリ使用率が80%以上でアラート、90%以上で自動スケール
  • 定期的なメモリ監査:月1回、freetopの傾向分析を習慣化

メモリ調査を自動化するスクリプト

本番環境で繰り返し使える統合診断スクリプトを紹介します。

#!/bin/bash
# memory_diagnosis.sh - メモリ不足の総合診断

echo "=== メモリ全体状況 ==="
free -h

echo -e "\n=== メモリ消費Top10プロセス ==="
ps aux --sort=-%mem | head -11 | tail -10

echo -e "\n=== スワップ状況 ==="
swapon -s

echo -e "\n=== OOM Killerの最近の活動 ==="
dmesg | grep "oom-kill" | tail -5

echo -e "\n=== ページキャッシュの詳細 ==="
cat /proc/meminfo | grep -E "MemTotal|MemFree|Buffers|Cached"

# オプション:CSV出力で時系列記録
if [ "$1" = "--log" ]; then
  TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
  AVAILABLE=$(free -b | awk 'NR==2 {print $7}')
  echo "$TIMESTAMP,$AVAILABLE" >> memory_history.csv
fi

実行方法:

chmod +x memory_diagnosis.sh
./memory_diagnosis.sh

# 定期実行(毎日午前3時に実行)
0 3 * * * /path/to/memory_diagnosis.sh --log

類似ツールとの比較

freetoppsの組み合わせで多くの場合は対応できますが、より詳細な分析にはツールの使い分けが有効です。

  • vmstat:メモリとCPU、ディスク I/O を総合的に監視(傾向分析向き)
  • htoptopより見やすいTUI(プロセスツリー表示が便利)
  • Grafana + Prometheus:長期的な監視・可視化(本番運用向き)

よくある質問

A: スワップの過度な使用は「スラッシング」を引き起こし、ディスク I/O が激増してシステム全体が極度に遅くなります。スワップは緊急避難用と捉え、根本的なメモリ不足は解決すべきです。ただし、適度なスワップ(物理メモリの10~20%程度)は、予期しない一時的なスパイク対策として有効です。

A: freeは単なる未使用メモリです。一方、availableはページキャッシュなど再利用可能なメモリも含めた、実質的にアプリケーションに割り当てられる容量を示します。メモリ不足の判定はavailableを優先すべきです。

A: 以下のコマンドで対応できます。

まとめ

  • free -hで全体状況を素早く把握し、availableカラムに注目する
  • ps aux --sort=-%mem
K
AWS・Python・生成AIを専門とするソフトウェアエンジニア。AI・クラウド・開発ワークフローの実践ガイドを執筆しています。詳しく見る →