「ディスクがいっぱいです」と警告が出たとき、まず知りたいのはどのくらい空きが残っているか、そして何が容量を食っているかの2つです。前者を調べるのが df、後者を調べるのが du です。名前も役割も似ていて混同しやすいコマンドですが、見ている対象がはっきり違います。この記事では、df と du の違いと使い分け、よく使うオプション、そして大きなディレクトリを効率よく探す実用例までを、実際のコマンドと出力例つきで解説します。
目次
df と du は何が違うのか
この2つのコマンドは、どちらもディスクの容量を扱いますが、見ている単位が異なります。df は「disk free」の略で、ファイルシステム(ドライブやパーティション)全体を対象に、合計容量・使用量・空き容量を表示します。一方 du は「disk usage」の略で、指定したファイルやディレクトリがどれだけの容量を使っているかを積み上げて計算します。
ざっくり言えば、df は「残りどれくらい?」を上から俯瞰するコマンド、du は「何が容量を食っている?」を下から掘り下げるコマンドです。空きが足りなくなったら、まず df でどのファイルシステムが逼迫しているかを確認し、次に du でその中の重いディレクトリを探す、という流れが基本になります。
df でディスクの空き容量を確認する
df をオプションなしで実行すると、マウントされている各ファイルシステムの容量が1キロバイト単位の数値で表示されます。ただこの数値は桁が大きく読み取りづらいので、実際にはほとんどの場合 -h を付けて使います。
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 38G 10G 80% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
/dev/sda2 200G 120G 70G 64% /home
# 左から「デバイス名」「合計」「使用量」「空き」「使用率」「マウント位置」
-h は「human-readable(人間が読みやすい)」の意味で、容量を G(ギガバイト)や M(メガバイト)といった単位に変換して表示してくれます。まず見るべきは Use%(使用率)と Avail(空き容量)の列です。上の例では、ルート(/)の使用率が80%まで来ているので、そろそろ整理が必要だと判断できます。
特定のディレクトリがどのファイルシステムに属しているかを知りたいときは、df にパスを渡します。そのパスを含むファイルシステムの情報だけが表示されます。
$ df -h /var/log
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 38G 10G 80% /
# /var/log は / と同じファイルシステム上にあると分かる
df でよく使うオプションは次の通りです。
| オプション | 効果 |
|---|---|
-h | G・M など人間が読みやすい単位で表示する(2進接頭辞、1024基準) |
-H | -h と同様だが1000基準で計算する(メーカー表記に近い) |
-i | 容量ではなく inode の使用状況を表示する |
-T | ファイルシステムの種類(ext4 など)も表示する |
-a | サイズ0の擬似ファイルシステムも含めてすべて表示する |
容量に空きがあるのに書き込めないとき(inode)
df -h では空きが十分あるように見えるのに、「No space left on device」と言われて書き込めない――そんなときは inode の枯渇を疑います。inode とは、ファイル1つ1つの管理情報(所有者や更新日時、データの位置など)を格納する領域で、ファイルシステムを作った時点で個数の上限が決まっています。小さなファイルを大量に作ると、容量よりも先に inode を使い切ってしまうことがあります。inode の使用状況は -i で確認できます。
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 3200000 3200000 0 100% /
# IUse% が 100% なら inode 切れ。容量が空いていても書き込めない
上の例のように IUse% が100%になっていれば、原因は容量ではなく inode 切れです。この場合は、大量に作られた小さなファイル(キャッシュやセッションファイルなど)を削除して inode を空ける必要があります。
du でディレクトリのサイズを確認する
du は、指定したディレクトリの容量を、その中のサブディレクトリごとに積み上げて表示します。こちらもオプションなしだと数値が読みづらいので、-h を付けるのが基本です。
$ du -h /var/log
4.0K /var/log/apt
120M /var/log/nginx
8.0K /var/log/private
340M /var/log
# サブディレクトリごとの容量が並び、最後に合計が出る
ただ、この形式だと深い階層のディレクトリまで1行ずつ表示されるため、ファイルが多い場所では出力が膨大になります。実際に使うときは、目的に応じてオプションで表示を絞り込むのがコツです。よく使うものを見ていきましょう。
| オプション | 効果 |
|---|---|
-h | G・M など人間が読みやすい単位で表示する |
-s | 個別の内訳を出さず、指定先の合計だけを表示する(summarize) |
--max-depth=N | N 階層より深いディレクトリは表示しない |
-a | ディレクトリだけでなくファイル単位でも表示する |
-c | 最後に総合計(total)の行を追加する |
合計だけを知りたいとき(-sh)
「このディレクトリ全体で何ギガあるか」だけを知りたいなら、-s(合計のみ)と -h を組み合わせた du -sh が定番です。内訳を出さず、指定した場所の合計サイズを1行だけ返します。
$ du -sh /var/log
340M /var/log
# 複数のディレクトリをまとめて調べることもできる
$ du -sh /home/*
2.1G /home/alice
890M /home/bob
15G /home/carol
2つ目の例のように /home/* とワイルドカードを渡すと、各ユーザーのホームディレクトリの合計を横並びで比較できます。誰が容量を使っているかを一目で確認したいときに便利です。
直下のディレクトリごとに見たいとき(–max-depth)
合計だけでは大まかすぎるけれど、深い階層まで全部出されても困る――そんなときは --max-depth=1 を付けます。指定したディレクトリの直下にあるものだけを、それぞれの合計サイズつきで表示してくれます。「どのサブフォルダが重いのか」を段階的に絞り込むのに最適です。
$ du -h --max-depth=1 /var
16M /var/cache
1.2G /var/lib
340M /var/log
2.0G /var
この結果を見て /var/lib が重いと分かったら、次は du -h --max-depth=1 /var/lib というように、対象を絞りながらもう一段掘り下げていきます。これを繰り返すことで、容量を食っている本当の犯人にたどり着けます。
大きいディレクトリをサイズ順に並べて探す
du の出力は名前順やディスク上の順番で並ぶため、そのままでは「どれが一番大きいか」がぱっと分かりません。そこで sort と組み合わせて、サイズの大きい順に並べ替えます。ここで役立つのが sort -h です。-h は du -h が出力する「1.2G」「340M」のような単位つきの数値を正しく大小比較してくれるオプションで、GNU sort に用意されています。
# -r で降順にすると大きい順になる
$ du -h --max-depth=1 /var | sort -hr
2.0G /var
1.2G /var/lib
340M /var/log
16M /var/cache
# du -h … 直下のディレクトリの容量を単位つきで出す
# sort -hr … 単位つきの数値を大きい順に並べる
この du -h ... | sort -hr の組み合わせは、容量調査の定番パターンです。上位だけ見たいときは、末尾に | head を足して件数を絞ると見やすくなります。ディスクの空きが逼迫したら、まず df -h で逼迫しているファイルシステムを特定し、そのマウント位置に対して du -h --max-depth=1 ... | sort -hr を上の階層から順にかけていく――この流れを覚えておくと、原因のディレクトリを素早く突き止められます。
df と du の合計が食い違うとき
du で数えた使用量の合計と、df が示す使用量が一致しないことがあります。特に「巨大なログファイルを削除したはずなのに、df の空きが一向に増えない」というのは、サーバー運用でよく出くわす現象です。これは、ファイルシステムの仕組みを知っていると理解できます。
Linux では、あるファイルを rm で削除しても、そのファイルをまだ開いているプロセスが存在する間は、実体(データ)が解放されません。ディレクトリからは消えるので du や ls の集計からは外れますが、プロセスがファイルを掴んでいる限り、その分の容量はディスク上に残り続けます。df はファイルシステムの実際の使用量を見ているため、この「消したのに残っているデータ」もカウントします。結果として、df の使用量が du の合計より大きくなるわけです。
典型的なのが、アプリケーションが書き込み中のログファイルを rm したケースです。プロセスはファイルへの参照を握ったままログを書き続けるため、容量は解放されません。どのプロセスが削除済みファイルを掴んでいるかは、lsof で調べられます。
# 削除済みだがプロセスが掴んでいるファイルを探す
$ lsof | grep deleted
nginx 1234 www-data 4w REG 8,1 524288000 789 /var/log/nginx/access.log (deleted)
# 524288000 バイト(約500MB)がまだ解放されていない
容量を実際に解放するには、そのファイルを掴んでいるプロセスを終了するか、再起動(あるいはログのリロード)します。上の例なら nginx を systemctl reload nginx などで再読み込みすれば、古いファイルハンドルが閉じられて容量が戻ります。「消したのに df が減らない」ときは、まず lsof | grep deleted を思い出してください。
まとめ
df はファイルシステム全体の空き容量を俯瞰するコマンドで、df -h で読みやすく表示し、Use% や Avail で逼迫具合を確認します。容量が空いているのに書き込めないときは df -i で inode 切れを疑いましょう。一方 du はディレクトリごとの使用量を調べるコマンドで、合計だけなら du -sh、直下ごとに見るなら du -h --max-depth=1、そして | sort -hr でサイズ順に並べれば重いディレクトリを効率よく探せます。空き不足のときは「df で当たりをつけ、du で掘り下げる」のが基本の流れです。もし削除したのに df の空きが増えなければ、プロセスが掴んだままの削除済みファイルを lsof | grep deleted で確認してみてください。