web-dev-qa-db-ja.com

開いているが削除されている大きなファイルを見つけて削除する

削除されたがまだアプリケーションで開いている大きなファイルをどのように見つけますか?プロセスが開いていても、そのようなファイルを削除するにはどうすればよいですか?

状況は、ログファイルを非常に多くの量でいっぱいにするプロセスを実行している場合です。理由はわかっています。修正できます。それまでは、プロセスをシャットダウンせずにログファイルをrmまたは空にしたいと思います。

単にrm output.logはファイルへの参照のみを削除しますが、プロセスが終了するまでディスク上のスペースを占有し続けます。さらに悪いことに、rmingの後で、ファイルの場所や大きさを見つける方法がなくなりました。別のプロセスでまだ開いている場合でも、ファイルを検索して空にする方法はありますか?

特に、DebianやRHELなどのLinuxベースのオペレーティングシステムについて言及します。

124
dotancohen

アプリケーションを強制終了できない場合は、ログファイルを削除する代わりに切り捨ててスペースを解放できます。ファイルが追加モードで開かれていない場合(_O_APPEND_を使用)、ファイルは次にアプリケーションがファイルに書き込むときと同じ大きさで表示されます(ただし、先頭部分はスパースであり、NULバイトが含まれているように見えます) )、ただしスペースは再利用されます(ただし、Apple OS/Xはスパースファイルをサポートしていません)のHFS +ファイルシステムには適用されません)。

それを切り捨てるには:

_: > /path/to/the/file.log
_

Linuxですでに削除されている場合でも、次のようにして切り捨てることができます。

_: > "/proc/$pid/fd/$fd"
_

ここで、_$pid_は、ファイルが開かれているプロセスのプロセスIDであり、_$fd_は、そのファイルが開かれている1つのファイル記述子です(_lsof -p "$pid"_で確認できます)。

Pidがわからず、削除されたファイルを探している場合は、次のことができます。

_lsof -nP | grep '(deleted)'
_

_lsof -nP +L1_、 @ user75021で言及されているように は、さらに優れた(より信頼性が高く、移植性の高い)オプションです(リンクが1つ未満のファイルをリストします)。

または(Linuxの場合):

_find /proc/*/fd -ls | grep  '(deleted)'
_

または、zshで大きなものを見つけるには:

_ls -ld /proc/*/fd/*(-.LM+1l0)
_

別の方法として、アプリケーションが動的にリンクされている場合は、デバッガーをアプリケーションに接続して、close(fd)を呼び出し、その後に新しいopen("the-file", ....)を呼び出します。

146

こちらのクイックスタートをご覧ください: lsof Quickstart

Lsofクイックスタートファイル(lsofに含まれている)について誰も言及していないことに驚いています。セクション「3.a」は、開いているリンクされていないファイルを見つける方法を示しています。

lsof -a +L1 *mountpoint*

例えば。:

[root@enterprise ~]# lsof -a +L1 /tmp
COMMAND   PID   USER   FD   TYPE DEVICE    SIZE NLINK  NODE NAME
httpd    2357 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
mysqld   2588  mysql    4u   REG 253,17      52     0  1495 /tmp/ibY0cXCd (deleted)
mysqld   2588  mysql    5u   REG 253,17    1048     0  1496 /tmp/ibOrELhG (deleted)
mysqld   2588  mysql    6u   REG 253,17       0     0  1497 /tmp/ibmDFAW8 (deleted)
mysqld   2588  mysql    7u   REG 253,17       0     0 11387 /tmp/ib2CSACB (deleted)
mysqld   2588  mysql   11u   REG 253,17       0     0 11388 /tmp/ibQpoZ94 (deleted)
httpd    3457   root   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8437 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8438 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8439 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8440 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8441 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8442 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8443 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8444 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   16990 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   19595 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   27495 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   28142 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   31478 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)

Red Hatシステムでは、クイックスタートファイルのローカルコピーを見つけるために、通常これを行います。

[root@enterprise ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART

...またはこれ:

[root@enterprise ~]# rpm -qd lsof
/usr/share/doc/lsof-4.78/00.README.FIRST
/usr/share/doc/lsof-4.78/00CREDITS
/usr/share/doc/lsof-4.78/00DCACHE
/usr/share/doc/lsof-4.78/00DIALECTS
/usr/share/doc/lsof-4.78/00DIST
/usr/share/doc/lsof-4.78/00FAQ
/usr/share/doc/lsof-4.78/00LSOF-L
/usr/share/doc/lsof-4.78/00MANIFEST
/usr/share/doc/lsof-4.78/00PORTING
/usr/share/doc/lsof-4.78/00QUICKSTART
/usr/share/doc/lsof-4.78/00README
/usr/share/doc/lsof-4.78/00TEST
/usr/share/doc/lsof-4.78/00XCONFIG
/usr/share/man/man8/lsof.8.gz
36
user75021

実際にはfree割り当てられたスペースはファイルシステムドライバーの責任です。これは通常、一度だけ発生しますallそのファイルを参照するファイル記述子が解放されます。したがって、アプリケーションでファイルを閉じない限り、実際にスペースを再利用することはできません。つまり、それを終了するか、デバッガで「少し」操作します(たとえば、ファイルを閉じて、再度開かれたり書き込まれたりしないようにするか、/dev/null代わりに)。または、カーネルをハックすることもできますが、それはお勧めしません。

Stephaneが示唆するようにファイルを切り捨てることは役立つかもしれませんが、実際の結果はファイルシステムにも依存します(たとえば、事前に割り当てられたブロックは、いずれにせよファイルを閉じた後にのみ解放される可能性があります)。

この動作の背後にある理論的根拠は、カーネルがそのようなファイルをターゲットとするデータ要求(読み取りと書き込みの両方ですが、読み取りは実際にはより重要です)をどう処理するかを知らないということです。

1
peterph