Fullmoon System

LinuxのNo space left on deviceを解決する:ディスク・inode・削除済みファイルの診断

EdwardMoon

LinuxでNo space left on deviceが出ると、ディスクが満杯だと考えがちです。しかし原因はブロック不足だけでなく、inodeの枯渇、削除後もプロセスが開いているファイル、マウント失敗、急増したログの場合もあります。

原因を調べずrm -rfで削除すると、調査に必要なログを失ったり、サービス停止を拡大させたりするおそれがあります。Rocky Linux、RHEL、CentOS、Ubuntuなど一般的なサーバーで使える診断順序と、安全な対処方法を説明します。

No space left on deviceの診断順序:findmnt、df、inode、du、lsof
No space left on deviceの原因別の診断順序

最初に実行する5つのコマンド

時間がなければ次の順に確認します。/pathには、失敗したパスと同じファイルシステムにある実在するディレクトリを指定します。ファイル作成に失敗して対象が存在しない場合は、最も近い親ディレクトリを使います。

# 1. エラーの発生したパスが属するファイルシステムを確認
findmnt -T /path
# 2. ファイルシステムのディスクブロック使用率を確認
df -hT /path
# 3. inode使用率を確認
df -i /path
# 4. 同じファイルシステム内で容量の大きいディレクトリを確認
sudo du -xhd1 /path 2>/dev/null | sort -h
# 5. 削除後もプロセスが開いているファイルを確認
sudo lsof +L1 2>/dev/null

注意:dufindは、ファイルが多いサーバーでディスクI/Oを増やす場合があります。サービス負荷を確認しながら範囲を絞って実行してください。

主な原因

原因代表的な症状最初の確認
ディスクブロック不足Use%が100%またはしきい値に近いdf -hT
inode枯渇容量は残っているが新規ファイルを作れないdf -i
開いたままの削除済みファイル削除してもdfの使用量が減らないlsof +L1
ログ・キャッシュの急増/varやルートの使用量が急増dujournalctl --disk-usage
マウント失敗別ディスク用のデータがルートへ蓄積findmnt -Tlsblk -f

診断1:ディスクブロックの使用率

df -hT
df -hT /var/log

dfはファイルシステムごとの総容量、使用量、空き、使用率、マウント先を示します。-hは読みやすい単位、-TはXFS・ext4などの種類を表示します。Use%に加え、一般ユーザーが使えるAvailも確認してください。ext4の予約ブロックにより、一般ユーザーには空きがなくてもrootには残っている場合があります。

全体の出力だけで判断せず、書き込みに失敗したパスと同じファイルシステムの実在ディレクトリを指定します。たとえば/data/app.logへ書けなければ、ファイル自体が未作成の可能性があるため、親の/dataを確認します。

findmnt -T /data
df -hT /data

ルートに空きがあっても、/dataが別ファイルシステムで満杯なら、その場所では作成できません。

診断2:inode使用率

df -i
df -i /var

inodeは、権限、所有者、サイズ、時刻、データ位置などのメタデータを管理する構造です。小さなファイルが大量にあると、容量より先にinodeを使い切る場合があります。ext4は作成時にinode数が決まり、XFSは動的に割り当てます。ただしXFSでもデータ・メタデータ領域が不足すると作成に失敗するため、df -idf -hTを併せて判断します。

IUse%が100%なら、大きなファイル数個より、不要な小ファイルを多数整理する方が有効です。ファイルの多い場所を次で探せます。

# /varと同じファイルシステム内でファイル数の多いディレクトリを確認
sudo find /var -xdev -type f -printf '%h\n' 2>/dev/null \
  | sort | uniq -c | sort -nr | head -n 30

セッション、アプリケーションキャッシュ、メールキュー、一時ファイルがよくある原因です。削除前には保持期間とサービスへの影響を必ず確認してください。

診断3:大きなディレクトリとファイル

ルートが満杯なら、まず最上位ディレクトリごとの使用量を確認し、大きい場所へ1段ずつ進みます。

sudo du -xhd1 / 2>/dev/null | sort -h
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo du -xhd1 /var/log 2>/dev/null | sort -h

-xは別ファイルシステムへ移らない指定です。-d1は集計結果の表示を1階層下までに制限します。合計のために深いファイルも走査するので、これだけでは探索量やI/Oは減りません。詳細はGNU du公式マニュアルを参照してください。

特定ファイルシステム内で1GBを超えるファイルを探す例です。

sudo find /var -xdev -type f -size +1G \
  -printf '%s %p\n' 2>/dev/null \
  | sort -nr | head -n 30

主な確認先は/var/log/var/cache/tmp/home/opt/var/lib/dockerです。ただし/var/libを手動削除するとDBやコンテナランタイムを壊す場合があるため、各サービスの正式な整理手順を使ってください。

診断4:開いたままの削除済みファイル

プロセスがファイルを開いている間は、名前を削除してもブロックは直ちに返りません。ディレクトリに見えずduで数えられなくても、FDが閉じるまではdfで使用中として残ります。

sudo lsof +L1 2>/dev/null

# サイズの大きい項目から確認
sudo lsof +L1 2>/dev/null \
  | awk 'NR>1 {print $7, $1, $2, $4, $9}' \
  | sort -nr | head -n 30

プロセス名、PID、FD、サイズを確認します。対処は、そのファイルを開いているサービスを正規手順で再起動するか、アプリケーションにファイルを開き直させることです。

sudo systemctl restart 서비스명
sudo lsof +L1 2>/dev/null
df -hT

本番では冗長性と影響を先に確認してください。原因不明のままkill -9で終了したり、/proc/PID/fdを強制的に空にしたりするとデータ損失や障害につながるため、初動には推奨しません。

5:systemd journalが大きい場合

journalctl --disk-usage

journalが多くの容量を占める場合は、古い保管ログをサイズまたは期間で整理できます。

# 現在のログを先に保管状態へ移し、保管ログを500MB以下へ整理
sudo journalctl --rotate --vacuum-size=500M

# 14日を超えた保管ログを整理
sudo journalctl --vacuum-time=14d

--vacuum-*は保管済みjournalを対象にします。現在のログも含めて直ちに整理するなら、--rotateと併用すると明確です。

再発防止として、配布元と運用方針に合わせて最大使用量を制限できます。

# /etc/systemd/journald.conf.d/10-size-limit.conf
[Journal]
SystemMaxUse=1G
RuntimeMaxUse=256M
sudo systemctl restart systemd-journald
journalctl --disk-usage

systemdに不慣れな場合は、systemdサービスの作成と構成要素も参照してください。

6:マウント失敗でルートへデータが蓄積した場合

/dataが別ストレージのはずでも、起動やネットワークの障害でマウントされないと、アプリケーションが同じパスのルートFSへ書き続ける場合があります。

findmnt -T /data
lsblk -f
systemctl --failed
journalctl -b -u '*.mount'

先に削除するのではなく、アプリケーションの書き込みを止め、元のFSのマウントを復旧します。マウントの下へ隠れたファイルの確認には、サービス影響と整合性を検討した保守手順が必要です。

dfとduの値が違う理由

dfはFSが割り当てたブロックを報告し、duは現在のディレクトリツリーから到達できるファイルを走査します。次の場合には値が異なります。

  • 削除後もプロセスが開いたままのファイル
  • FSのメタデータと予約領域
  • 権限不足でduが読めないディレクトリ
  • 下層へマウントされた別FS
  • スナップショットとCopy-on-Writeの共有ブロック

dfduの差が大きい場合は、まずlsof +L1とマウント構造を確認するとよいでしょう。

本番サーバーの復旧順序

  1. 失敗パスの特定:実際の書き込み先とFSを確認する。
  2. 増加原因の抑制:ログ暴走や反復ジョブなど、使用量を増やす原因を先に止める。
  3. 証拠の保全:必要なログと状態を別の場所へ保存してから整理する。
  4. 正式な整理:logrotate、journal vacuum、アプリケーションのキャッシュ整理を優先する。
  5. 復旧の検証:ディスク・inode、ファイル作成、サービス、アプリケーションログを再確認する。
df -hT /path
df -i /path
touch /path/.write-test && rm -f /path/.write-test
systemctl --failed

再発防止チェックリスト

  • 容量だけでなくinode使用率も監視する。
  • 警告と危険のしきい値を分け、増加速度も見る。
  • アプリケーションログにlogrotateか独自の保持方針を設ける。
  • journalの最大サイズと保持期間を運用方針に合わせる。
  • Docker、DB、バックアップ製品は製品固有の整理機能を使う。
  • /var/log、データ、バックアップを分け、1領域の増加がOS全体へ波及するのを減らす。
  • マウント失敗中にローカルへ書き続けないよう、依存関係と事前検査を設定する。

よくある質問

空き容量があるのにエラーが出るのはなぜですか

まずinode使用率と、実際の失敗パスが属するFSを確認してください。df -hに空きがあっても、df -iが100%、または別マウントが満杯なら作成に失敗します。

ログを削除してもdfが減らないのはなぜですか

プロセスが開いたままの可能性があります。lsof +L1で特定し、正規の再起動またはファイルの開き直しを行うと、空きが返ります。

/var/logをすべて削除してもよいですか

推奨しません。障害原因や監査記録を失い、再作成時の権限問題が起きる場合もあります。logrotate、journalctl vacuum、製品のログ整理機能を使ってください。

duが遅すぎる場合はどうしますか

-d1は表示深度だけを制限し、下層の走査は続きます。失敗したFSと疑わしいパスへ絞って調べてください。-xは他FSの調査を防ぎます。同じツリーを何度も走査しないよう結果を保存し、ファイルの多いサーバーではI/O負荷が低い時間帯に実施します。

まとめ

No space left on deviceの解決は削除から始めません。findmntで対象FS、df -hTでブロック、df -iでinode、duでディレクトリ使用量、lsof +L1で開いたままの削除済みファイルを順に確認します。

原因を分けた後、ログ保持方針、サービス再起動、マウント復旧など適切な処置を選ぶことで、データ損失と再発を防げます。

参考資料