Linuxでファイルを削除しても容量が減らない|lsofで原因調査

RHEL10とspace not freedの文字を配した、ファイル削除後も容量が解放されない問題の記事のアイキャッチ Linuxサーバ
スポンサーリンク

1. ファイルを削除しても空き容量が増えないとき

Linuxサーバで不要なログを削除したのに、空き容量が増えていない。さらにファイルを消す前に、削除したファイルを動作中のプログラムがまだ開いていないかを確認しましょう。

この記事では、df と du で使用量の変化を比べ、lsof で削除済みファイルを開いているプログラムを探します。対処後に空き容量が戻ったことを確認するまで、実際の画面で解説します。

【注意】この症状が必ず同じ原因とは限りません。実サービスの強制終了や、開いているファイルの強制切り詰めは主手順にしません。通常の調査は確認操作ですが、再現例には専用テストファイルの作成・削除が含まれます。

2. dfとduの違い:どこの容量を見ているか

ファイル名を削除することと、プロセスがファイルを閉じることは別の操作です。名前が消えてもプロセスの参照が残っていれば、データ領域が使われ続けることがあります。

確認方法このケースで見えるもの
dfファイルシステム全体の使用量。参照が残る削除済みファイルの領域も使用中として残る
duパスからたどって集計した使用量。名前が消えたファイルは集計できない
lsofプロセスが開いているファイル。削除済みでも保持中なら確認できる場合がある

du はフォルダー内の使用量で、空き容量ではありません。空きを見るのは df の「使用可」欄です。二つの数字を引き算せず、それぞれの削除前後を比べます。

3. 空き容量が増えないとき、最初に何を調べるか

まず df で対象のファイルシステムを確認し、次に lsof で削除済みファイルを開いているプログラムを探します。

最初に、問題の書き込み先が属するファイルシステムを確認します。次は /var を調べる例です。実際の既存パスに置き換えてください。

df -hT /var

続けて、必要な閲覧権限で削除済みのオープンファイルを調べます。lsofが未導入なら、導入は管理者の変更手順に従ってください。

lsof -nP +L1

+L1はリンク数が1未満のオープンファイルを選ぶ指定です。出力のPID、FD、TYPE、DEVICE、NODE、NAMEを見て、問題のファイルシステムに属するファイルかを照合します。関係のないファイルも表示されるので、(deleted)があるだけで原因と決めないでください。

例えば対象PIDが2055だと分かったら、そのPIDと削除済みという条件をANDで絞れます。数字は今回の撮影時の値で、実サーバでは自分の調査結果に置き換えます。

lsof -nP -a -p 2055 +L1

広い対象へのlsofやduは環境によって時間・負荷がかかります。また、dfがファイルシステム全体、duが一部のディレクトリだけなら、値が違って当然です。比較する範囲と単位を先にそろえます。

4. 実測① 削除前の使用量を確認する

ここからは約67 MBのテストファイルを使った検証です。削除前に、du で検証フォルダーの使用量、df でファイルシステム全体の使用量を記録します。

項目今回の撮影環境
OSRed Hat Enterprise Linux 10.2(Coughlan)
ファイルシステム/dev/sda2、XFS、マウント先 /
coreutils9.5-8.el10_2.1
lsof4.98.0-7.el10
保持プロセス検証用のbashシェル、撮影時PID 2055
テストファイル64MiB、FD 9で読み書き用にオープン

【再現例の前提】ここからは、専用検証サーバで自作したテストファイルを使った記録です。容量を満杯にする試験ではありません。業務ログやDBファイルを削除して再現しないでください。

約67 MBのテストファイルを開いたまま削除し、最後に閉じました。目的は、空き容量がどの時点で戻るかを確かめることです。画像の67,108,864バイトは、別の単位では64 MiBです。

LAB_DIR は検証用フォルダーの場所です。以下は準備済みの検証シェルでの記録です。検証フォルダーは片付け済みなので、そのままコピーして実行しないでください。

ls -lh "$LAB_DIR/held-demo.bin"
df -B1 "$LAB_DIR"
du -B1 -s -x "$LAB_DIR"
lsof -nP -a -p "$$" -d 9
RHEL10で64MiBの検証ファイルと、そのファイルをFD 9で保持するbashを確認している画面
削除前:検証フォルダーは64 MiB。ここを削除後と比べます。

画像の du の行は 67,108,864バイト(64 MiB)。ファイルを作ったことで検証フォルダーが使っている量です。df の「使用」欄は 2,559,209,472バイト。これは検証ファイルだけでなく、/ 全体で使っている量です。

5. 実測② ファイルを削除しても空き容量は増えない

テストファイルを開いたまま削除し、削除前と同じ場所を測ります。du の使用量と df の「使用可」がどう変わるかを見ます。

次は今回の専用テストファイルだけを削除した操作です。本番向けの推奨削除コマンドではありません。-iの確認で対象を確かめてから削除しました。

rm -i -- /var/tmp/blog-deleted-space.sRVVur/held-demo.bin

削除後、同じ対象で確認します。この時点ではFD 9を閉じていません。

ls -la "$LAB_DIR"
df -B1 "$LAB_DIR"
du -B1 -s -x "$LAB_DIR"
検証ファイルの削除後にduが0となり、dfの使用量は変わっていない画面
変わらなかった数字: df の「使用」は2,559,209,472バイトのまま。「使用可」も増えていません。プログラムが開いたままなので、データの領域はまだ空いていません。

変わった数字: du は67,108,864 → 0バイト。ファイル名が消え、フォルダーからたどれなくなったためです。

6. 実測③ 削除したファイルを開いたままのプログラムを見つける

lsof で、どのプログラムが削除済みのファイルをまだ開いているか確認します。画像ではファイル名の (deleted) と、プログラム名の bash に注目します。

lsof -nP -a -p "$$" +L1
ps -p "$$" -o pid,ppid,user,comm
readlink /proc/$$/fd/9
lsofでbashのPID 2055、FD 9u、NLINK 0と削除済みファイルを確認している画面
容量が減らない理由:削除済みのファイルを bash がまだ開いています。
表示項目今回の結果確認すること
COMMAND / PIDbash / 2055保持しているプロセス
FD9uファイル記述子9、読み書き用
TYPE / DEVICEREG / 8,2通常ファイルと対象デバイス
NODE33947270削除前と同じファイルを追う手掛かり
NLINK0名前へのリンクが残っていない
NAMEheld-demo.bin (deleted)削除済みでも参照が残る状態

まず画像の NAME 欄の (deleted) と、COMMAND 欄の bash を見ます。「名前は削除済みだが、今回の検証で使った bash がまだ開いている」という意味です。SIZE/OFF の 67,108,864 は、今回のファイルのサイズです。

補足:$$ は、コマンドを入力したシェル自身のプロセス番号です。今回は 2055 でした。9u の 9 は、そのプログラム内で開いているファイルの管理番号、u は読み書き用の意味です。実際の調査で 9u を探す必要はありません。SIZE/OFF の値も、常に解放される容量を示すわけではありません。

7. 実測④ ファイルを閉じると空き容量が戻る

検証用のプログラムがファイルを閉じた後、同じ場所を測り直します。du が0バイトのままでも、df で約67 MBの空きが戻ったことを確認できます。

次は、検証用の bash が開いていたテストファイルだけを閉じた記録です。bash やSSH接続そのものは終了させていません。

【重要】exec 9>&-は、そのコマンドを実行したシェルのFD 9を閉じます。他の業務プロセスが持つFDを閉じる汎用の復旧コマンドではありません。今回の検証以外で、用途不明のFDに対して実行しないでください。

exec 9>&-
df -B1 "$LAB_DIR"
du -B1 -s -x "$LAB_DIR"
lsof -nP -a -p "$$" +L1
検証シェルのFD 9を閉じた後にdfの使用量が減り、lsofの対象表示がなくなった画面
解放後:検証フォルダーは0バイトのまま。df の「使用」が64 MiB減りました。
状態dfの使用量(bytes)専用ディレクトリのdu(bytes)
削除前2,559,209,47267,108,864
削除後・FD保持中2,559,209,4720
FDを閉じた後2,492,100,6080

画像の df の「使用」欄は 2,559,209,472 → 2,492,100,608バイト。du は 0バイトのままです。lsof にも今回のファイルは表示されなくなりました。ファイルを閉じたことで、ファイルが使っていた領域が解放され、この検証では空き容量が 67,108,864バイト(64 MiB)増えました。他の書き込みがある環境では、前後の差がファイルサイズと一致するとは限りません。

検証後は空の専用ディレクトリも削除し、残っていないことを確認しました。撮影時のディレクトリはもう存在しません。

8. 実サーバで空き容量を取り戻すには

ここからは実サーバでの対処です。検証用の操作をそのまま使わず、対象のサービスに合った方法でファイルを閉じてもらいます。

1. 対象を特定する。 第3章の lsof でファイル名・プログラム名・プロセス番号を確認します。問題のファイルシステムにあるファイルか確かめ、サービスの担当者に用途と業務影響を確認します。

2. ファイルを閉じてもらう。 ログなら、公式手順でログを開き直せるか確認します。複数のプロセスが開いていれば、一つ閉じても、ほかが開いている間は領域は戻りません。開き直しで解消できない場合は、影響と復旧手順を確認し、計画した時間に正常停止・再起動を検討します。

3. 空きを測り直す。 同じファイルシステムの df の「使用可」を確認し、lsof で対象が残っていないか見ます。検証用の exec 9>&- は本番の復旧コマンドではありません。強制終了や、開いているファイルの強制切り詰めは避けてください。

lsofに候補が出なければ、閲覧権限・警告・対象範囲・状態変化を確認します。NFSのストレージ側の保持やスナップショット等、別原因もあります。候補なしだけで問題なしと判断せず、別の切り分けへ進みます。

9. まとめ・関連記事

調査の流れは「対象ファイルシステム → 削除済みのオープンファイル → PID・FDの照合 → 影響確認と対処 → 解放後の再確認」です。ファイル削除と参照解放の違いを意識すると、削除を繰り返す前に調べるべき場所が分かります。

lsofの他の用途は、ファイルや通信からプロセスを特定するlsofの使い方で補足しています。サービスの状態やログを調べる場合は、systemctlとjournalctlで起動失敗を確認する手順も参照してください。

参考:Red Hatの削除後も容量が解放されない事例、lsof公式マニュアル。上記の操作結果・数値・画像は、RHEL 10.2で撮影した今回の検証に基づきます。

コメント

タイトルとURLをコピーしました