free -h の出力を1列ずつ解剖
「free が少ない」と焦る必要はない。Linuxが空きメモリをキャッシュに回すのは正常な動作だ。free -h の6列を1つずつ読み解き、本当に見るべき available とSwapの判断基準を身につける。
- free -h のfree列はどこにも使われていない完全な遊休ページを指し、少ないことは異常ではない。Linuxは余った物理メモリをページキャッシュに回すよう設計されており、稼働時間の長い健全なサーバーほどfreeは小さくなる。
- buff/cacheはディスク内容を保持するページキャッシュなどで、メモリが必要なら解放できる。見るべきはfreeよりavailableで、キャッシュ解放後に新しいプロセスへ渡せる量をカーネルが見積もった値だ。
- Swapが数百MiB使われていても異常とは限らず、起動直後から触られていないページが追い出されただけのことが多い。危険なのはスワップインとアウトが継続する状態で、判断はfreeの数値ではなくvmstatのsi/so列で行う。
このコマンドは何を見せているか
freeがやっていることは驚くほど単純だ。/proc/meminfo を読み、いくつかの行を足し引きして整形する。それだけである。free自身が測定している値は1つもなく、出てくるのはすべてカーネルが持つ統計そのものだ。freeを読めるとは、カーネルがメモリをどう扱うかを理解しているのと同じことだ。
-h はhuman-readableの略で、バイト数を1024基数で丸めてGiやMiを付ける。桁を数えずに済むので、対話的に確認するときは常に付けてよい。
出力はMem行とSwap行の2行しかない。Mem行が物理メモリ、Swap行がスワップ領域を表す。そしてこれは瞬間のスナップショットだ。1回叩いた結果から傾向は読めない。推移を追うなら free -s 1 で繰り返すか、topの出力やvmstatを併用する。
available列は procps-ng 3.3.10(2014年)で追加された。それ以前は「-/+ buffers/cache」という2段目の行があり、ネット上の古い解説はこの旧形式を前提にしていることがある。手元の出力にavailable列があるかが、その解説が現行かの目印になる。
横にスクロール
1列ずつ解剖
題材は、メモリ16GBのLinuxサーバーでアプリケーションを数日間動かした後の、ごく平凡な出力だ。
$ free -h
total used free shared buff/cache available
Mem: 15Gi 6.6Gi 401Mi 121Mi 8.6Gi 8.4Gi
Swap: 4.0Gi 512Mi 3.5Gi
freeが401Mi、空きは全体の3パーセントを切っている。ここで「メモリが足りない」と判断するなら、この記事はまさにそのために書かれている。結論から言えば、このサーバーは健全だ。
total — カーネルの管理下にある物理メモリ
/proc/meminfo のMemTotalに対応する。16GBのマシンで15Giと出るのが普通で、カタログ値とは一致しない。差分はファームウェアの予約領域やカーネル自身を載せた領域など、カーネルが割り当て対象として扱っていない部分だ。起動後は変化しないので、読み飛ばしてよい列である。
used — 実測ではなく引き算の残り
最初の落とし穴がここだ。usedは「プロセスが確保した量の合計」ではない。他の列から差し引いた残り物であり、しかもその式はprocpsのバージョンで変わっている。
| procps-ngのバージョン | usedの定義 | このサンプルでの値 |
|---|---|---|
| 3.3.10〜3.3.17(RHEL 9、Ubuntu 22.04など) | total - free - buff/cache | 6.0Gi |
| 4.0以降(Debian 12、Ubuntu 24.04など) | total - available | 6.6Gi |
同じ瞬間の同じマシンでも、procpsのバージョンが違えばusedの表示は食い違う。しかも4系では used + free + buff/cache がtotalを超えうる。サンプルでも合計は15.6Gi相当となり、totalの15Giを上回る。列を足して合わないと悩む必要はない。合わないのが仕様だ。
共通するのは、usedが引き算の結果であって内訳を持たないことだ。どのプロセスがどれだけ使っているかはfreeからは分からない。知りたければtopやpsへ行くしかない。
free — どこにも貸し出していない遊休メモリ
MemFreeに対応し、本当に何にも使われていないページの量だ。そしてこの列が少ないことは、問題の兆候ではない。
Linuxの設計思想は明快である。空いている物理メモリは1バイトも価値を生まない。ならば余っている間はディスクの内容を覚えておくために使う。一度読んだファイルの中身を保持しておけば、次に同じ場所を読むときディスクへ行かずに済むからだ。その保持先がページキャッシュで、buff/cache列に計上される。
したがって、稼働時間の長い健全なサーバーほどfreeは小さくなる。起動直後にfreeが大きいのは、まだキャッシュに入れるものが無いだけだ。逆に何日も動いてfreeが大きいままなら、それは「このマシンはほとんど仕事をしていない」というサインだ。
shared — tmpfs と共有メモリ
Shmemに対応し、tmpfs(/dev/shm や多くのディストリビューションの /run)とPOSIX/System Vの共有メモリの合計だ。
注意点が2つある。1つ目は、sharedがbuff/cacheの別枠ではなく、その内訳を一部取り出して見せている列にすぎないこと。2つ目は、性質が他のキャッシュと違うことだ。通常のページキャッシュはディスクにファイル実体があるので捨てても読み直せばよいが、tmpfsの中身は捨てればそのまま消える。だからsharedの分は回収できず、availableの計算でも回収可能とは見なされない。/dev/shm に巨大なファイルを置いたまま忘れる事故は珍しくない。
buff/cache — いつでも捨てられる「貸し出し中の空き」
Buffers(ブロックデバイスのメタデータ用バッファ)、Cached(ページキャッシュ)、SReclaimable(inodeやディレクトリエントリのキャッシュなど回収可能なスラブ)の合計である。
この8.6Giは失われたメモリではない。空きが足りなくなると、カーネルはこの中のクリーンなページ、つまりディスクの内容と一致していて書き戻しの要らないページを黙って捨て、その場所を要求元に渡す。ユーザーから見れば一瞬で、アプリケーションは何も気付かない。例外はダーティページで、捨てる前にディスクへの書き戻しが要る。とはいえ通常それはごく一部だ。
available — 実質的に唯一見るべき列
MemAvailableに対応する。Linux 3.14で /proc/meminfo に追加された比較的新しい値だ。意味は「新しくアプリケーションを起動したとき、スワップを起こさずに使えると見込まれる量」。カーネルがfreeと回収可能なキャッシュを足し、回収できない分と最低限確保しておく水準(watermark)を差し引いて見積もる。
サンプルでは8.4Gi。total 15Giの半分以上がまだ渡せる。free列の401Miとは20倍以上の開きがある。監視のしきい値を置くなら、置く場所はここしかない。
| 列 | 実体 | 少ないと問題か |
|---|---|---|
| free | どこにも使われていない完全な遊休ページ | いいえ。少ないのが健全な状態 |
| buff/cache | いつでも回収できるキャッシュ | いいえ。多いほど性能上は有利 |
| available | キャッシュ回収後に新規プロセスへ渡せる見積もり | はい。ここが尽きると危険 |
Swap行 — 追い出されたページの置き場
Swap行はtotal・used・freeの3列だけだ。usedは、物理メモリから追い出されていまディスク上のスワップ領域にいるページの量を指す。
ではなぜ、availableが8.4Giも残っているのに512Miもスワップされているのか。カーネルは、長時間アクセスされていない匿名ページ(ファイルに紐付かないヒープやスタックなど)を、メモリが逼迫する前でも先回りしてスワップへ移すことがあるからだ。積極性は vm.swappiness パラメータで調整する。起動時に一度動いたきり眠っている常駐プロセスの初期化コードなどが、この512Miの正体であることが多い。二度と触られないページに物理メモリを占有させるより、その分をページキャッシュへ回した方が全体は速くなる。合理的な判断の結果なのだ。
つまずきやすい点
第一に、そして圧倒的に多い誤解が、freeの小ささに焦ることだ。401Miを見て増設を検討したり、キャッシュを飛ばして「空きを増やす」対処を打ったりする。しかしLinuxにとって空きメモリは無駄でしかなく、余りをキャッシュへ回すのは仕様どおりの正常動作だ。見るべきはavailableであり、free列は事実上ノイズだと思ってよい。
第二に、buff/cacheが大きいことはメモリ不足の証拠ではない。/proc/sys/vm/drop_caches に3を書き込めばキャッシュは捨てられ、free列の数字は劇的に増える。だが増えるのは数字だけだ。次にそのファイルが読まれた瞬間にディスクI/Oが発生し、キャッシュは同じ水準まで戻る。availableはほとんど変わらない。性能を捨てて見た目を良くする操作であり、本番で常用する理由はない。
第三に、Swapのusedがゼロでないこと自体は異常ではない。危険なのは「使われている量」ではなく「動いている勢い」の方だ。スワップインとアウトが継続する状態、いわゆるスラッシングに陥ると、CPUがディスク待ちで埋まり全体が数十倍遅くなる。この判定にfreeは使えない。vmstat 1 のsi列とso列、すなわち1秒あたりのスワップイン量とアウト量が動き続けているかを見る。usedが512Miのまま動かないなら、それはただの置き土産だ。
第四に、OOM Killerが動く条件を取り違えないこと。カーネルがプロセスを強制終了させるのは、freeがゼロに近づいたときではない。キャッシュを回収し尽くしてもなお割り当て要求を満たせないとき、つまりavailableが示す余地を使い切ったときだ。逆に言えば、freeが数百Miまで減ってもavailableに余裕があるうちはOOM Killerは動かない。この境界さえ理解していれば、free列の小ささに振り回されずに済む。ページキャッシュや仮想メモリの仕組みはOS側で扱っている。
コンテナ内でfreeを実行しても、表示されるのはホスト全体の値だ。freeは /proc/meminfo を読むが、これは既定でcgroupの制限を反映しない。コンテナに与えた上限と実使用量を知りたければ、cgroupのmemory.maxとmemory.currentを直接読む必要がある。コンテナ内のfreeを根拠にメモリ不足を判断してはならない。
まとめ
free -h の6列のうち、日常的に意味を持つのはavailableとSwap行の動きだけだ。totalは起動後変わらず、usedはバージョン依存の引き算の残り、freeは小さいのが正常、sharedとbuff/cacheは貸し出し中の空き、availableこそが渡せる量である。Swapは残量ではなくsi/soの勢いで判断する。この読み替えができた瞬間から、free -h は3秒で状況を伝える道具に変わる。他のコマンドの読み方はコマンド出力の読み方にまとめている。
コマンド出力の読み方の記事ガイド
free -h の出力を1列ずつ解剖を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
コマンド出力
比較で見る軸
難易度: advanced / カテゴリ: コマンド出力の読み方 / タグ数: 4
導入後に効く点
buff/cacheはディスク内容を保持するページキャッシュなどで、メモリが必要なら解放できる。見るべきはfreeよりavailableで、キャッシュ解放後に新しいプロセスへ渡せる量をカーネルが見積もった値だ。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- コマンド出力の読み方
- タグ数
- 4
判断チェックリスト
- 自社の用途が「コマンド出力 / Linux」に近いか確認する。
- 強みである「free -h のfree列はどこにも使われていない完全な遊休ページを指し、少ないことは異常ではない。Linuxは余った物理メモリをページキャッシュに回すよう設計されており、稼働時間の長い健全なサーバーほどfreeは小さくなる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。