ENOSPC(No space left on device)
書き込みが突然「No space left on device」で止まる原因を、df だけ見ても空きがあるのに直らない罠まで含めて逆引きできる。削除済みファイルの掴みと inode 枯渇の切り分けで最短復旧できる。
- ENOSPC は write(2)・open(2) 等が返すエラーで、ブロック容量の枯渇と inode の枯渇という別々の原因がある。df -h が空きを示していても inode が尽きれば発生する。
- 消したはずのファイルをプロセスが開いたままだと inode は解放されず、df の空きは戻らない。lsof +L1 で nlink=0 の削除済みファイルを掴むプロセスを特定し、再起動かログローテートで解放する。
- 診断は df -h(ブロック)と df -i(inode)を必ず両方見て、du で肥大箇所を絞り、Docker では layer・volume・build cache を prune する。予防はローテート・監視・quota。
一言でいうと(このエラーが何を意味するか)
ENOSPC は「No space left on device」に対応する POSIX のエラー番号(errno の 28)で、write(2)・open(2)(O_CREAT)・mkdir(2)・rename(2) などがデータを書き込めなかったときにカーネルが返します。アプリ側では write: No space left on device や Node.js の Error: ENOSPC として表面化します。
重要なのは、原因が 2 種類あることです。1 つはブロック(データ本体を置く領域)の枯渇。もう 1 つは inode(ファイルのメタデータ枠)の枯渇です。ext4 などは作成時に inode 数が固定されるため、1 バイトの空きが山ほどあっても inode を使い切ればもう 1 ファイルも作れず ENOSPC になります。df -h だけを見て「空いているのに直らない」と詰まる典型がこれです。
ディスク全体は空いていても、ユーザー/グループ quota を超えると EDQUOT(Disk quota exceeded)が返ります。メッセージが「Disk quota exceeded」なら本記事の df ではなく quota -v や repquota を見ます。文言で切り分けてください。
横にスクロール
よくある原因(複数を具体的に、頻度順)
- ログ・一時ファイルの肥大: ローテート未設定のアプリログ、
journald、/tmp、APT/yum キャッシュがパーティションを埋める。最頻出。 - 削除したのに空きが戻らない: プロセスが開いているファイルを
rmしても、ファイルのnlink(ハードリンク数)は 0 になるがプロセスが握るファイルディスクリプタが残る限り inode とブロックは解放されない。ログをrmしたのにサーバーの空きが増えない、という症状の正体。 - inode 枯渇: メールキュー、セッションファイル、npm の
node_modules、大量の小ファイルを作るバッチが inode を食い尽くす。df -hは余裕、df -iが 100%。 - Docker のディスク肥大: 未使用の image layer・停止コンテナ・匿名 volume・build cache が
/var/lib/dockerを埋める。ホストのENOSPCの主犯になりやすい。 - 予約ブロックの壁: ext 系は既定で 5% を root 用に予約する。一般ユーザーのプロセスは 95% の時点で
ENOSPCを食う(dfは使用率 95% 前後を示す)。 - 特殊要因: inotify の watch 上限超過(
ENOSPCを返すが実ディスクは無関係。エディタやwebpack --watchで頻発)、スパースファイルの実書き込み、スナップショット領域の消費など。
Linux の unlink はディレクトリエントリを消すだけで、開いているファイルの実体はプロセスが閉じるまで残ります。だから肥大ログを消しても、それを追記中のプロセスがいれば空きは戻りません。プロセスの再起動、または : > /path/to/log(truncate)でその場の実体を縮めるのが正攻法です。
診断の手順(切り分け方・見るべきログ/コマンド)
まずブロックと inode を両方確認します。ここを片方だけで済ませるのが最大の落とし穴です。
df -h # ブロック容量。Use% と Mounted on を見る
df -i # inode 使用率。IUse% が 100% なら inode 枯渇
どのマウントが満杯かを特定したら、その配下で消費元を絞ります。
# 大きいディレクトリ上位(対象FS内に限定して他マウントへ潜らない)
du -x -h --max-depth=1 /var | sort -rh | head -20
# inode枯渇時は「大きさ」でなく「ファイル数」で探す
find /var -xdev -printf '%h\n' | sort | uniq -c | sort -rn | head -20
「消したのに戻らない」を疑うときは、削除済み(nlink=0)を掴むプロセスを特定します。
# +L1 は「リンク数が1未満=削除済みだが未クローズ」のファイルだけを表示
lsof +L1
# 出力の NLINK 列が 0、SIZE/OFF が巨大なものが原因。PID を再起動 or truncate
| 症状 | df -h | df -i | 有力な原因 | 次の一手 |
|---|---|---|---|---|
| 空きゼロ | 100% | 余裕 | ログ・キャッシュ肥大 | du -x で肥大箇所を特定し削除/ローテート |
| 消しても戻らない | 高いまま | 高いまま | 削除済みをプロセスが保持 | lsof +L1 → 再起動 or truncate |
| 空きあるのにENOSPC | 余裕 | 100% | inode枯渇 | find で小ファイル群を特定し整理 |
| Docker周辺で発生 | 100%(/var) | どちらも有り得る | layer/volume/cache肥大 | docker system df → prune |
Docker が絡む場合は専用の内訳コマンドが早いです。
docker system df # image/container/volume/build cache の内訳
docker system df -v # 個別サイズの詳細
解決と予防(対処と再発防止)
対処は「原因の種類」で分岐します。
# 1) 肥大ファイルの縮小(追記中のプロセスを止めずに実体だけ0に)
: > /var/log/huge.log # rm ではなく truncate。fd はそのまま生きる
# 2) 削除済み保持の解放:lsof +L1 で見つけた PID を再起動、または
truncate -s 0 "/proc/<PID>/fd/<N>" # 該当fdの実体を縮める最終手段
# 3) journald の肥大を上限付きで整理
journalctl --vacuum-size=200M
# 4) Docker の不要データを一括回収(volume も消すなら --volumes は慎重に)
docker system prune # 停止コンテナ・未使用network・dangling image・cache
docker image prune -a # 未参照 image を全削除
inode 枯渇は「削除」でしか回復しません。ext4 は後から inode 数を増やせず、増やすには作り直し(mkfs -N/-i)が要ります。小ファイルが構造的に多いなら、inode を動的確保する XFS や Btrfs への移行が根本策です。予約ブロックはデータ用途のパーティションなら tune2fs -m 1 /dev/sdXN で 5%→1% に下げて実効容量を稼げます。
- ログは
logrotateと journald のSystemMaxUse=で必ず上限を設ける - 監視は「容量」と「inode」を別メトリクスで、80% でアラート(100% では手遅れ)
- ユーザー/プロジェクト単位の暴走は
quotaで封じ込める - inotify の
ENOSPCはfs.inotify.max_user_watchesをsysctlで引き上げる(ディスクとは無関係)
ファイルシステムの inode・ハードリンク・unlink の内部動作はOS、コンテナのレイヤ管理と /var/lib/docker 肥大の背景はDevOps、テーブルスペースや WAL でディスクを食う DB 側の枯渇はデータベースを参照してください。
- ENOSPC は errno 28。ブロック枯渇と inode 枯渇は別原因で、後者は df -h に空きがあっても起きる
- 削除済みファイルは開いているプロセスがある限り解放されない(unlink は nlink を減らすだけ)。lsof +L1 で特定
- 診断は df -h と df -i を必ず併用。inode は「大きさ」でなく「ファイル数」で追う
- ext4 の inode 数は作成時固定で後から増やせない。XFS は動的確保
エラー辞典の記事ガイド
ENOSPC(No space left on device)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
Linux
比較で見る軸
難易度: advanced / カテゴリ: エラー辞典 / タグ数: 6
導入後に効く点
消したはずのファイルをプロセスが開いたままだと inode は解放されず、df の空きは戻らない。lsof +L1 で nlink=0 の削除済みファイルを掴むプロセスを特定し、再起動かログローテートで解放する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- エラー辞典
- タグ数
- 6
判断チェックリスト
- 自社の用途が「Linux / ファイルシステム」に近いか確認する。
- 強みである「ENOSPC は write(2)・open(2) 等が返すエラーで、ブロック容量の枯渇と inode の枯渇という別々の原因がある。df -h が空きを示していても inode が尽きれば発生する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。