Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】rm Freed Nothing and df Stayed Full: Finding the Process Still Holding a Deleted Camera Clip

2026年10月20日に「Dev.to」が公開したITニュース「rm Freed Nothing and df Stayed Full: Finding the Process Still Holding a Deleted Camera Clip」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Linuxで`rm`コマンドでファイルを削除しても、別のプロセスがそのファイルをまだ開いていると、ディスク容量は解放されない。これはファイルの実体への参照が残るため。`lsof`や`/proc`で開いているファイルとプロセスを特定できる。プロセスが終了すれば容量は解放される。また、`/proc`経由でファイルを切り詰める方法や、削除前に`fuser`でファイル利用を確認する予防策もある。

ITニュース解説

Linuxシステムを扱う上で、時々遭遇する「ファイルを削除したはずなのに、ディスクの空き容量が減らない」という現象について解説する。この現象は一見バグのように思えるが、実はLinuxのファイル管理の仕組みを理解すると納得できる振る舞いである。

ディスクの空き容量を確認するにはdfコマンドを、特定のディレクトリのファイルサイズを確認するにはduコマンドを使う。ファイルを削除する際にはrmコマンドを利用するが、rm実行後、lsコマンドではファイルが消えたように見えても、dfコマンドで確認するとディスク使用状況は削除前と変わらないことがある。これはなぜだろうか。

この現象の核心は、Linuxのファイルシステムにおける「ファイルの削除」の定義にある。通常、rmコマンドでファイルを削除すると、そのファイル名がディレクトリから消え、ファイルが占めていたディスクスペースが解放されると期待するだろう。しかし、Linuxでは、もしあるプロセスがそのファイルをまだ開いている場合、たとえファイル名が削除されても、ファイルの実体はディスク上に残り続け、そのディスクスペースは解放されない。ファイルが実際にディスクから消滅し、そのスペースが再利用可能になるのは、そのファイルを開いていた最後のプロセスが終了し、ファイル記述子(ファイルへの参照)がすべて閉じられた時なのだ。

この動作を具体的に検証する実験が行われた。まず、仮想的な「レコーダー」プロセスをPythonスクリプトで作成し、200MiB(メガバイト)のファイルにデータを書き込み、ファイルを閉じずに開いたままにした。この状態でdfコマンドでディスク使用量を計測すると、200MiB分のディスク容量が増加している。次に、この開かれたままのファイルをrmコマンドで削除した。すると、dfの表示は相変わらず200MiB増加したままだった。しかし、duコマンドで該当フォルダのサイズを確認すると、たった4KiB(キロバイト)と表示された。これは、rmがファイル名(ディレクトリへのエントリ)を削除しただけで、ファイルの実体はまだ存在しており、dfはその実体が占めるブロックを認識していることを示している。

では、この問題を特定し解決するにはどうすればよいか。ファイルが「削除済みだが開かれたまま」の状態にあることを特定するのに役立つツールがいくつかある。

一つはlsofコマンドだ。これは「List Open Files」の略で、システム上の開いているファイルを一覧表示する強力なツールである。特定のプロセスが保持している、名前が削除されたファイルを見つけるには、lsof -nP -a +L1 -p <PID>というコマンドが有効だ。ここで、-p <PID>は特定のプロセスID(PID)に限定して検索し、+L1は「unlinkされた(名前が削除された)開いているファイル」を意味する。特に重要なのは-aオプションで、これは複数の選択オプションをAND条件で結合することを意味する。もし-aを付けずにlsof +L1 -p <PID>とすると、+L1の条件を満たすすべてのファイル(削除済みファイル)と、<PID>のプロセスが開いているすべてのファイルをOR条件で表示してしまうため、誤った結果を招くことがある。lsofの出力にはNLINKというカラムがあり、これが0であれば、そのファイルにはもうディレクトリからの名前がないことを示している。

もう一つ、lsofがインストールされていない環境でも利用できる方法として、/procファイルシステムを直接参照する方法がある。Linuxでは、/proc/<PID>/fdというパスに、各プロセス(<PID>)が現在開いているファイル記述子がシンボリックリンクとして表示される。ファイルが削除されて名前がなくなった場合、このシンボリックリンクのターゲットに「(deleted)」という表記が追加されるため、find /proc/<PID>/fd -lname '*(deleted)'のようなコマンドで特定できる。

ファイルが特定できたら、ディスクスペースを解放する方法を考える。最も確実でクリーンな方法は、そのファイルを開いているプロセスを正常に終了させることだ。プロセスが終了すれば、それに伴って開いているファイル記述子も閉じられ、ディスクスペースは自動的に解放される。実際、上記の実験でも、ファイルを保持していたPythonプロセスを終了させると、dfの表示は直ちに元の状態に戻り、スペースが解放されたことが確認できた。

しかし、場合によっては、プロセスを停止させることが望ましくないこともある。例えば、長時間稼働中のレコーダープロセスを中断したくない場合だ。このような状況でも、ディスクスペースを解放する方法がある。それは、/proc/<PID>/fd/<FD>というパスを通じて、該当するファイル記述子を直接「切り詰める(truncate)」方法である。具体的には、: > /proc/<PID>/fd/<FD>のようなシェルコマンドを使うことで、プロセスを終了させずにファイルの内容をゼロサイズにできる。これにより、dfの表示は直ちに元の状態に戻り、ディスクスペースが解放される。ただし、この方法には注意が必要だ。ファイルを切り詰めた後も、元のプロセスはファイルを開いたままであり、以前の書き込み位置を記憶している。そのため、もしプロセスが再度ファイルに書き込みを行うと、その書き込みはファイルの先頭からではなく、以前の書き込みオフセット(今回の例では200MiBの位置)から行われる。結果として、ファイルの見かけのサイズは大きくなるが、実際にディスク上に割り当てられるブロックは追記された部分のみとなり、先頭のほとんどの部分は「穴」として存在する「スパースファイル」となる。この「穴」部分はディスク容量を消費しないが、ファイルを読み出すとゼロとして扱われるため、後からファイルを開いたアプリケーションが元のデータを期待すると、意図しない動作になる可能性がある。

このような問題が頻繁に発生するのを防ぐための予防策も存在する。ファイルクリーンアップのスクリプトで、ファイルを削除する前に、そのファイルが他のプロセスによって開かれているかどうかをチェックすることが有効だ。fuser -s <file>コマンドは、指定されたファイルが開かれている場合に成功を示す終了コードを返す。このコマンドを使って、開いているファイルは削除せずスキップするようにすれば、意図せず「削除済みだが開かれたまま」のファイルが発生するのを防ぐことができる。しかし、fuserでチェックしてからrmを実行するまでの間に、別のプロセスがファイルを開いてしまうという「競合状態」が稀に発生する可能性もゼロではない。より堅牢な方法としては、ファイル書き込みプロセスが書き込みを終えたら、そのファイルを「処理済み」や「完了済み」といった専用のフォルダに移動させ、クリーンアップスクリプトはその「完了済み」フォルダ内のファイルのみを対象とする、という運用が考えられる。

実際にシステム上でdfとduの表示が大きく食い違っている状況に遭遇した場合、以下のような手順で調査を進めることができる。まず、df -hとdu -shを比較し、大きな差があることを確認する。次に、root権限でlsof -nP +L1を実行し、システム上のすべての「削除済みだが開かれているファイル」と、それらを保持しているプロセスを特定する。もしlsofが使えない環境であれば、同様にroot権限で/proc/*/fdを検索し、(deleted)とマークされたリンクを探す。これらの情報に基づいて、該当するプロセスを終了させるか、再起動させるか、あるいは/proc経由でファイルを切り詰めるかといった対応を決定することになる。

この問題はext4のような一般的なLinuxファイルシステムで発生するが、NFSのようなネットワークファイルシステムでは挙動が異なる場合がある。また、プロセスがファイルを直接のファイル記述子ではなく、メモリマップトファイルとして開いている場合もあり、その場合は/proc/<PID>/mapsを参照して調べる必要がある。ファイルをrmコマンドで削除しても、そのファイルを開いているプロセスが存在する限り、ディスクスペースは解放されない。ディスクの空き容量は、ファイル名が消えたかどうかではなく、そのファイルを誰も参照していないかどうかによって決まる、ということを理解しておくことが、Linuxシステムを安定して運用するために非常に重要である。

関連コンテンツ

関連IT用語