背景と必要性
深夜2時、ディスク使用率が95%を突破し、PagerDutyのアラートが鳴り響く――これはインフラエンジニアなら誰もが経験する悪夢でしょう。反射的にターミナルを開いて叩くのは、どのパーティションが逼迫しているかを確認するdf -hコマンドです。そして、それに続いてうんざりするようなコマンドdu -sh /* 2>/dev/null | sort -hrを実行することになります。
しかし、この従来の手法には2つの致命的な弱点があります。第一に、duコマンドはディスクI/Oに非常に大きな負荷をかけます。HDDやTBクラスの大規模ストレージでは、サーバー全体のボトルネックになりかねません。第二に、ターミナルに出力されるテキスト一覧は見づらく、配下のサブディレクトリを調査するために何度もコマンドを再実行する必要があります。
新米時代、筆者はMySQLサーバーで手痛い失敗を経験しました。/varパーティションの使用率が100%に達し、パニックになりながらduの乱雑な出力と格闘していたとき、肥大化していた40GBのバイナリログ(binlog)ではなく、誤ってソケットファイルmysql.sockを削除してしまったのです。データベースはクラッシュし、45分以上もの不要なダウンタイムを引き起こしてしまいました。
このインシデント以降、本番環境の全サーバーの標準構成にdufとncduを即座に導入しました。
- duf (Disk Usage/Free Utility):
dfの完全な代替ツールです。物理ディスク、NFSネットワークドライブ、仮想パーティション(tmpfs)を自動的にグループ化します。カラー表示のテーブル形式とプログレスバーにより、極めて直感的なインターフェースを提供します。 - ncdu (NCurses Disk Usage):
duを大幅に進化させたTUI(Text User Interface)ツールです。矢印キーでディレクトリツリーを探索し、リアルタイムでディスク占有率を確認しながら、その場で不要なファイルを直接削除できます。
インストール
両ツールとも最適化された言語(ncduはC/Zig、dufはGo)で記述されており、メモリ消費が非常に少なく、主要ディストリビューションの公式リポジトリから簡単に導入できます。
1. Ubuntu / Debianの場合
sudo apt update
sudo apt install -y ncdu duf
古いバージョンのUbuntu(APTリポジトリにdufパッケージが含まれていない20.04 LTSなど)を使用している場合は、GitHubのリリースから直接バイナリを取得してインストールします。
curl -LO https://github.com/muesli/duf/releases/download/v0.8.0/duf_0.8.0_linux_amd64.deb
sudo dpkg -i duf_0.8.0_linux_amd64.deb
rm -f duf_0.8.0_linux_amd64.deb
2. RHEL / Rocky Linux / AlmaLinuxの場合
RHEL系ディストリビューションでは、ncduをインストールする前にEPELリポジトリを有効化します。
sudo dnf install -y epel-release
sudo dnf install -y ncdu
dufは公式RPMパッケージからインストールします。
sudo dnf install -y https://github.com/muesli/duf/releases/download/v0.8.0/duf_0.8.0_linux_amd64.rpm
3. Arch Linuxの場合
sudo pacman -S ncdu duf
詳細な設定と実践テクニック
インストールが完了したら、実際のトラブルシューティングに活用していきましょう。
1. dufでシステム全体の状況を把握する
単にdufと入力するだけで、ターミナル上にLocal Devices、Inaccessible Devices、Special Devicesが一覧表示されます。ただし、実際の運用サーバーでは実データを保存している物理ディスクに焦点を絞るのが賢明です。
仮想パーティション(snapのsquashfsやtmpfsなど)を除外して表示する場合:
duf --only local
逼迫している箇所を即座に特定するために、使用量順(降順)でソートする場合:
duf --sort used
Inodeの使用状況を確認する場合:
duf --inodes
このオプションは厄介なトラブルで役立ちます。ディスク容量(バイト数)は数十GB余っているとdfが表示しているにもかかわらず、「No space left on device」エラーが出る場合です。その多くは、アプリケーションが数百万個におよぶ0バイトのセッションファイルやキャッシュファイルを生成し、inodeテーブルを枯渇させていることが原因です。
Tips:日常的に使いやすくするため、筆者は~/.bashrcにエイリアスを登録しています。
echo 'alias df="duf --only local"' >> ~/.bashrc
source ~/.bashrc
2. ncduで原因箇所を特定・クリーンアップする
dufでどのパーティションが逼迫しているかを把握したら、ncduを使って問題の原因となっているディレクトリやファイルを特定します。
ルートパーティションを安全にスキャンする場合:
sudo ncdu -x /
-x(one filesystem)フラグには特に注意してください: このフラグを指定すると、ncduは同一のルートファイルシステム内のみをスキャンします。外付けディスクやNFS共有などの別マウントポイント、さらには仮想ファイルシステム(/proc、/sysなど)へスキャンがまたがるのを防ぎます。このフラグを付け忘れると、無限ループに陥ったり、メモリを過剰に消費するリスクがあります。
肥大化しやすいコンテナデータディレクトリを除外してスキャンを高速化する場合:
sudo ncdu -x --exclude /var/lib/docker/overlay2 /
3. ncduの主要ショートカットキー
ncduのTUI画面では、キーボードのみで直感的に操作できます。
- 上 / 下矢印キー(または j / k): ファイルやディレクトリ間を移動。
- Enter(または右矢印キー): 選択したディレクトリを開く。
- 左矢印キー: 親ディレクトリに戻る。
- d: 選択中のファイルまたはディレクトリを削除。完全削除の前に確認ポップアップが表示されます。
- g: 容量グラフ表示の切り替え(パーセンテージ、プログレスバー、非表示)。
- i: 詳細情報パネルを表示(絶対パス、inode番号、パーミッションなど)。
- n: ファイル名順にソート。
- s: ファイルサイズ順にソート(デフォルト:降順)。
- q: プログラムを終了。
4. 高負荷(High Load)サーバー向けオフラインスキャン
本番サーバー上で直接ディレクトリをブラウズすると、ディスクI/Oを長時間占有してしまう可能性があります。毎秒数千リクエストを処理するような高負荷システムでは、一度だけスキャンを実行して圧縮ファイルに出力し、それを読み込む運用が効果的です。
# 1回だけスキャンしてgzip圧縮ファイルに出力(-1フラグで高速スキャン後に即終了)
sudo ncdu -1xo- /var/log | gzip > /tmp/ncdu_var_log.json.gz
# 新たなディスク読み込みを発生させずにデータを閲覧・操作
zcat /tmp/ncdu_var_log.json.gz | ncdu -f -
クリーンアップ後の確認と監視
数十GBの古いログを削除できたからといって、すぐにSSH接続を切断してはいけません。解放したディスク容量がOSによって実際に回収されたかを確認する必要があります。
1. 空き容量の再確認
まずはdufを実行して全体像をチェックします。
duf --only local
2. 削除済みファイルを開いたままにしているプロセスの罠(Deleted Open Files)
ncduで30GBのaccess.logを削除したにもかかわらず、dufで確認すると空き容量が1バイトも増えていないことがあります。慌てる必要はありません。Nginxプロセスがそのファイル記述子(ファイルディスクリプタ)を開いたまま保持しているのが原因です。Linuxでは、プロセスがファイルハンドルを解放して初めて、物理データブロックが実際に解放されます。
削除済みファイルを開いたまま保持しているプロセスを特定するコマンド:
sudo lsof +L1 | grep '(deleted)'
このコマンドによって対象サービスのPIDが出力されます。該当サービスにファイルハンドルの解放(リロード)を指示します。
sudo systemctl reload nginx
再度dufを実行すると、数十GBの空き容量が正常に回復していることが確認できます。
3. JSON出力を活用したアラートの自動化
dufの優れた機能の1つに、--jsonフラグによるJSON出力のサポートがあります。これを利用すれば、SlackやTelegramへの定期的なアラート通知スクリプトを極めてシンプルに記述できます。
#!/usr/bin/env bash
set -euo pipefail
# ルートパーティション(/)の使用率(%)を取得
USAGE=$(duf --json | jq '.[] | select(.mount_point=="/") | .used_percent')
if (( $(echo "$USAGE > 90" | bc -l) )); then
echo "警告: $(hostname) の / パーティションの使用率が ${USAGE}% に達しました!" | mail -s "[Disk Alert] $(hostname) のディスク残量警告" [email protected]
fi
全体像の把握にはduf、詳細な調査と削除にはncduを組み合わせることで、サーバーのディスク逼迫トラブルが発生した際の手作業と復旧時間を大幅に削減できます。

