du と df の違い - ディスク容量を正しく測る
この記事でできるようになること
- `df` はファイルシステム単位、`du` はディレクトリ単位という視点の違いを説明できる
- `df -h` `df -i` `du -sh` `du -h --max-depth=1` を目的に応じて使い分けられる
- `df` と `du` がズレる 3 つの原因を挙げ、`lsof | grep deleted` で確かめられる
前提知識(先に読むと理解しやすい記事)
この記事で解決できること
duとdfの 役割の違い を説明できます- 「
dfは満タンなのにduで計算しても合わない」現象の 原因 が分かります - 「削除したのに容量が戻らない」事件を 自力で解決 できます
- ディスクが足りなくなったときの 調査の型 が身につきます
対象読者:Linux 入門者。du と df を感覚で使い分けている方。
言葉の整理
- ファイルシステム:ディスクを区切って使うための仕組みです。この記事では「
/や/homeのように独立して容量を数える単位」と考えてください。 - マウント:ディスクをディレクトリファイルをまとめて整理する入れ物。Windows や macOS の「フォルダ」と同じもの。に結びつけて使える状態にすることです。結びつけた場所を「マウントポイント」と呼びます。
- inode:ファイル 1 つ 1 つの管理情報を入れる札です。札の数には上限があります。
- プロセス:実行中のプログラムのことです。
sudo:管理者の権限でコマンドを実行するための命令です。他人のファイルを調べるときに必要です。実行するとパスワードを聞かれることがあります。- パイプ(
|):左のコマンドの結果を右のコマンドに渡す記号です。A | Bで「A の結果を B で処理する」という意味になります。 grep:文字を探し出すコマンドです。grep deletedなら「deleted という文字を含む行だけ残す」という意味です。
この記事の中心は df と du です。どちらも表示するだけのコマンドで、ファイルを消したり書きかえたりしません。何度実行してもディスクの中身は変わりません。安心して試してください。
なお、記事の後半には削除や再起動をともなうコマンドも出てきます。そこには個別に注意書きを付けています。
導入:リナのディスクパンク事件
du で大きいファイルを探したんですけど、合計しても全然容量が足りません。どうしてですか?du と df のズレ」だね。これを正しく理解している人は意外と少ないんだ。du と df って似たコマンドじゃないんですか?結論を先に
df= ファイルシステム単位 の空き容量(マウントポイントごと)du= ディレクトリ・ファイル単位 の使用量(指定パスファイルやディレクトリの場所を表す文字列。以下を集計)- 一致しないのは 削除済み開きファイル / マウント境界 / rootすべての操作が許可された特別な管理者ユーザー。 予約ブロック が主因
2 つの視点のたとえ
冷蔵庫を思いうかべてください。df は「冷蔵庫にどれだけ空きがあるか」を外から見る係です。du は「棚ごとに何がどれだけ入っているか」を中から数える係です。
同じ冷蔵庫を見ていますが、数え方が違います。だから答えがずれることがあります。
df - ファイルシステム単位で空きを見る
結論:
dfはマウントポイントごとに全体・使用・空きを一瞬で表示する。-hと-iの両方を確認する。
df だよ。「disk free」の略だね。ファイルシステム単位で「全体・使用済み・空き」を表示するよ。/(ルート)、/home、USB メモリの /mnt/usb などが、別々に数えられるんだ。実際に試してみよう
$ df -h
Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 42G 5.5G 89% / tmpfs 1.9G 0 1.9G 0% /dev/shm /dev/sda2 100G 60G 40G 61% /home
読み方
Filesystem:デバイス名(/dev/sda1など)Size:全体容量Used:使用済みAvail:空きUse%:使用率(90% を超えたら警戒)Mounted on:マウントポイント
-h は何ですか?--human-readable の略だよ。50G や 5.5G のように 人間が読みやすい単位 で表示してくれる。-h を付けない df は KB 表示になる。桁を数えるのが大変だね。52428800 と出てきても、すぐには分かりません。よく使うオプション
$ df -h # 人間が読みやすい単位(G, M, K) $ df -T # ファイルシステムの種類も表示(ext4, xfs など) $ df -i # 使用量ではなく inode 数を表示 $ df -h /var # 特定パスが属するファイルシステムだけ
df -i を忘れない
ディスク容量に余裕があるのに「No space left」エラーが出ることがあります。その場合は inode の枯渇 が原因かもしれません。小さいファイルが大量にあると起こります。
df -h と df -i は 両方確認する習慣 をつけましょう。
du - ディレクトリ単位で使用量を測る
結論:
duはファイルを実際に走査して使用量を計算する。-shで合計、sort -hで大きい順に並ぶ。
du だよ。「disk usage」の略だね。指定したディレクトリ以下のファイルを 実際に走査して 使用量を計算するよ。du を実行すると 時間がかかる ことがある。df が一瞬で返ってくるのと対照的だね。実際に試してみよう
$ du -sh /var/log
1.2G /var/log
よく使うオプションの組み合わせ
-s(summary):合計だけ表示-h(human-readable):人間が読める単位--max-depth=N:N 階層まで表示
-sh はワンセットで覚えると便利。
階層別に大きいディレクトリを探す
$ du -h --max-depth=1 /var
4.0K /var/games 1.2G /var/log 512M /var/cache 24M /var/lib 1.7G /var
サイズ順に並べる
$ du -sh /var/* 2>/dev/null | sort -h
4.0K /var/games 4.0K /var/opt 24M /var/lib 512M /var/cache 1.2G /var/log
ポイント
2>/dev/null:権限が足りず読めないディレクトリのエラーメッセージを捨てますsort -h:単位付きの数字を正しく並べます(1.2Gを512Mより大きいと判定します)
sort -n(数値ソート)には注意が必要です。1.2G の 1.2 だけを見るため、小さい扱いになります。
du と df の決定的な違い
結論:
dfはファイルシステム単位、duはディレクトリ単位で見る。見ている階層が違うのでズレる。
比較表
| 項目 | df | du |
|---|---|---|
| 単位 | ファイルシステム | ディレクトリ・ファイル |
| 取得方法 | スーパーブロックから取得 | 実際にファイルを走査 |
| 速度 | 一瞬 | 大きいパスでは遅い |
| 削除済み開きファイル | 含まれる | 含まれない |
| 別マウント | 別物として集計 | 跨いで集計(-x で抑制可) |
| root 予約ブロック | 影響あり | 影響なし |
df では 90% なのに、du では 60% しか使っていない」ということが起こるんですね。ズレの主犯:削除済み開きファイル事件
結論: 削除しても開いているファイルは
dfだけがカウントする。lsof | grep deletedで見つけて解放する。
df と du がズレる 一番多い原因 がこれだよ。「削除したのに、まだ誰かが開いているファイル」だね。リナの失敗:ログを消したのに容量が戻らない
/var/log/nginx/access.log を rm で消しました。500 MB もあったのに、df -h の空き容量が 1 バイトも増えません。消し方を間違えたんでしょうか。$ df -h /
Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 42G 5.5G 89% /
rm してもファイルの実体がすぐには消えないことがあるんだ。du は名前をたどって数えるから、この分を見つけられない。df はファイルシステムから見た使用量だから、この分を数えるんだ。df と du がズレたら、まず開きっぱなしのファイルを疑います。rm は「名前を消すコマンド」と考えるといい。実体が解放されるのは、それを開いている全員が閉じたあとだよ。削除済み開きファイルを見つける
$ sudo lsof | grep deleted
nginx 1234 root 5w REG 8,1 524288000 ... /var/log/nginx/access.log (deleted) mysqld 5678 mysql 7w REG 8,1 104857600 ... /tmp/ibdata.tmp (deleted)
読み方
- 列 1:プロセス名(
nginx,mysqld) - 列 2:PID(プロセス ID。プロセスに付く番号です)
- 列 7:サイズ(バイト単位)
- 末尾の
(deleted):削除済みなのに開かれている印です
lsof は「list open files」の略です。開かれているファイルを一覧するコマンドで、表示するだけです。実行してもファイルは変わりません。
解放するには
# 該当プロセスを再起動 or リロード $ sudo systemctl restart nginx $ sudo systemctl reload mysql # プロセスが特定できれば、再起動なしで切り離す方法もある(上級者向け) # /proc/<PID>/fd/<N> を /dev/null にリダイレクトする手法など
再起動の前に必ず影響範囲を確認
systemctl restart はサービスをいったん止めます。失敗すると、その間サービスが応答しなくなります。
本番サーバーで実行する前に、次の 2 点を確認してください。
- サービスが止まってよい時間帯か
- そのサービスに依存している別のサービスはないか
安全に試したい場合は、まず学習用の環境か、止めても影響のないサービスで練習してください。詳しくは ディスクがいっぱい を参照してください。
ズレの第二犯:マウント境界
結論:
duは既定でマウント境界を跨いで集計する。dfと揃えるには-xを付けて同一 FS に限定する。
/home が別パーティションになっているとしよう。そこで du -sh / を実行すると、どうなると思う?/home も含めて全部足される、でしょうか。du は既定で マウントポイントを跨いで集計する んだ。df は別ファイルシステムを別物として数える。だから du -sh / の数字が、df の / の使用量より 大きく出る ことがあるんだよ。# マウント境界を跨がない(その FS だけ集計) $ sudo du -sh -x /
-x(--one-file-system)
これを付けると du は 指定パスと同じファイルシステムだけ を集計します。df との比較がしやすくなります。
ズレの第三犯:root 予約ブロック
結論: ext4 は root 用に約 5% を予約する。
dfのAvailは予約分を差し引くため数字が合わない。
df の Avail はこの予約分を 差し引いた値 なんだ。だから Size - Used と Avail が一致しないように見えるんだよ。# 予約ブロックの割合を確認 $ sudo tune2fs -l /dev/sda1 | grep -i reserved
Reserved block count: 655360 Reserved blocks uid: 0 (user root) Reserved blocks gid: 0 (group root)
予約ブロックを減らすのは慎重に
tune2fs -m 1 /dev/sda1 を実行すると 1% に減らせます。ただし、この操作はファイルシステムの設定を書きかえます。
システム領域では予約を 残しておくのが基本 です。減らすとしても、データ専用パーティションだけにしてください。
なお tune2fs -l(一覧表示)は読むだけの操作です。設定は変わりません。
実務で使う「調査の型」
結論:
df -hで俯瞰、df -iで inode 確認、duで大きいディレクトリ特定、lsofでズレ調査の順に動く。
ディスク調査の型(上から順に)
- 全体を俯瞰:
df -h(どのファイルシステムが満タンか) - inode も確認:
df -i(小さいファイル大量問題) - 大きいディレクトリを特定:
sudo du -h --max-depth=1 / 2>/dev/null | sort -h dfとduがズレてたら:sudo lsof | grep deleted- 古いログを削除:
/var/log配下の.gzなどを確認 - 解放されない時:該当サービスを
systemctl restart
各ステップのコマンド集
# 1. 全体を俯瞰 df -h # 2. inode 確認 df -i # 3. 大きいディレクトリ特定(root から 1 階層ずつ深掘り) sudo du -h --max-depth=1 / 2>/dev/null | sort -h sudo du -h --max-depth=1 /var 2>/dev/null | sort -h sudo du -h --max-depth=1 /var/log 2>/dev/null | sort -h # 4. 削除済み開きファイル sudo lsof | grep deleted | sort -k7 -n -r | head # 5. 大きいファイル単位で探す sudo find / -type f -size +100M 2>/dev/null
ミニ課題:自分の環境で試してみよう
結論: 使用率確認・大きいディレクトリ Top3・
dfとduの差分説明の 3 問で理解を定着させる。
lsof や --max-depth は本サイトの仮想ターミナル入力したコマンドを解釈してコンピュータに実行させる対話プログラム。には入っていないんだ。sudo が使えない環境なら、自分のホームディレクトリの中だけで試そう。課題 1: 自分の / パーティションの使用率を確認しよう。
ヒント 1(方向づけ)を見る
ファイルシステム単位で空きを見る側のコマンドを使います。ディレクトリを 1 つずつ数える必要はありません。
読みやすい単位で表示するオプションも付けます。
ヒント 2(コマンド名)を見る
使うのは df です。読みやすい単位は -h です。調べたい場所として / を指定します。
答えを見る
$ df -h /
Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 42G 5.5G 89% /
Use% の列が / の使用率です。90% を超えたら片づけを検討してください。
課題 2: ホームディレクトリの直下で、最も大きいディレクトリ Top 3 を見つけよう。
ヒント 1(方向づけ)を見る
今度はディレクトリごとに数える側のコマンドを使います。深くもぐらず、1 階層だけ見れば十分です。
そのうえで大きい順に並べ、末尾の数行を取り出します。
ヒント 2(コマンド名)を見る
使うのは du です。階層を 1 つに絞るのは --max-depth=1 です。並べかえは sort -h です。
末尾の行を取り出すのは tail です。一番下は全体の合計になるので、1 行多めに取ります。ホームディレクトリは ~ と書けます。
答えを見る
$ du -h --max-depth=1 ~ 2>/dev/null | sort -h | tail -4
64M /home/user/Documents 512M /home/user/Downloads 1.2G /home/user/Videos 2.5G /home/user
sort -h は小さい順に並べます。だから末尾を取れば大きい方が取れます。
一番下の行はホームディレクトリ全体の合計です。その上の 3 行が Top 3 です。だから tail -4 にしています。
課題 3: df -h / と sudo du -sh -x / の数字を比べ、差が出る理由を 1 行で説明しよう。
ヒント 1(方向づけ)を見る
まず 2 つの数字を並べて見ます。そのうえで、この記事で挙げた 3 つの原因を思い出してください。
どちらか一方だけが数えるものがあります。
ヒント 2(コマンド名)を見る
df -h / と sudo du -sh -x / を続けて実行します。差が大きいときは sudo lsof | grep deleted も実行します。
答えを見る
$ df -h / $ sudo du -sh -x / $ sudo lsof | grep deleted | head
差が出る主な理由は次の 3 つです。
- 削除済みだが開いているファイル(
dfだけが数えます) - 別のマウントポイントの存在(
du -xで除外していない場合) - ext4 の root 予約ブロック(
dfのAvailに影響します)
1 行でまとめるなら「df はファイルシステムから見た使用量、du は名前をたどった使用量なので、名前のないデータの分だけずれる」となります。
よくある落とし穴
結論:
dfの数字だけで消す・全削除する操作は危険。消す前にls -lhで確認しtruncateも検討する。
やってはいけない 3 つのパターン
du -sh /をnohupなしで本番で実行する → SSH が切れると途中で止まりますdfの数字だけを見てファイルを消す → 削除済み開きファイルが原因のときは効果がありませんrm -rf /tmp/*で全部を消す → 起動中のアプリの作業ファイルを壊します
安全な型
duはどの書き方でも、指定した場所より下をすべて数えます。走査量そのものは減りません- 表示だけを絞るなら
sudo du -h --max-depth=1 / 2>/dev/null | sort -hを使います。1 階層ごとの合計が見えるので、次にどこを掘るか決められます - 時間がかかる調査は
tmuxやscreenの中で実行します。接続が切れても止まりません - 消す前に
ls -lhで サイズと更新日時を確認します - 大きいログは消さず、
truncate -s 0 ファイル名で 中身だけを空にします
3 つ目について補足します。truncate -s 0 はファイルの中身を空にする操作です。中身は戻せません。ただし、ファイル自体は残るため、プロセスが開いたままでも安全に容量を解放できます。
先に ls -lh でサイズを見て、消してよい内容かを確かめてから実行してください。
振り返り
df はファイルシステム単位、du はディレクトリ単位で数えるんですね。sudo lsof | grep deleted を先に実行する。この順番だけ覚えておけば大丈夫だよ。今日の 3 行まとめ
dfはファイルシステム単位の空き、duはディレクトリ単位の使用量を見る- ズレの主な原因は「削除済み開きファイル」「マウント境界」「root 予約ブロック」の 3 つ
- 調べる順番は
df -h→df -i→du --max-depth=1→lsof | grep deleted