dot*_*hen 142 process logs disk-usage open-files files
如何找到已被删除但仍在应用程序中打开的大文件?即使进程打开了这样的文件,如何删除它?
情况是我们正在运行一个正在以极快的速度填充日志文件的进程。我知道原因,我可以解决它。在那之前,我想在不关闭进程的情况下 rm 或清空日志文件。
简单地执行rm output.log仅删除对文件的引用,但它会继续占用磁盘空间,直到进程终止。更糟糕的是:在rming之后我现在无法找到文件在哪里或有多大!有没有办法找到该文件,并可能清空它,即使它仍然在另一个进程中打开?
我特指基于 Linux 的操作系统,例如 Debian 或 RHEL。
Sté*_*las 174
如果你不能杀死你的应用程序,你可以截断而不是删除日志文件来回收空间。如果文件没有以追加模式打开(使用O_APPEND),那么在应用程序下一次写入文件时,文件将显示为与之前一样大(尽管前导部分稀疏并且看起来好像包含 NUL 字节),但空间将被回收(这不适用于 Apple OS/X 上不支持稀疏文件的 HFS+ 文件系统)。
截断它:
: > /path/to/the/file.log
Run Code Online (Sandbox Code Playgroud)
如果它已经被删除,在 Linux 上,你仍然可以通过执行以下操作来截断它:
: > "/proc/$pid/fd/$fd"
Run Code Online (Sandbox Code Playgroud)
$pid打开文件的进程的进程 id在哪里,以及$fd在其下打开的一个文件描述符(您可以使用lsof -p "$pid".
如果您不知道 pid,并且正在查找已删除的文件,您可以执行以下操作:
lsof -nP | grep '(deleted)'
Run Code Online (Sandbox Code Playgroud)
lsof -nP +L1,正如@user75021 所提到的,是一个更好(更可靠和更便携)的选项(列出少于 1 个链接的文件)。
或(在 Linux 上):
find /proc/*/fd -ls | grep '(deleted)'
Run Code Online (Sandbox Code Playgroud)
或者找到大的zsh:
ls -ld /proc/*/fd/*(-.LM+1l0)
Run Code Online (Sandbox Code Playgroud)
如果应用程序是动态链接的,另一种方法是将调试器附加到它并使其调用close(fd)后跟一个新的open("the-file", ....).
小智 42
在此处查看快速入门:lsof快速入门
我很惊讶没有人提到 lsof 快速启动文件(包含在 lsof 中)。“3.a”部分显示了如何查找打开的、未链接的文件:
lsof -a +L1 *mountpoint*
Run Code Online (Sandbox Code Playgroud)
例如:
[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)
Run Code Online (Sandbox Code Playgroud)
在 Red Hat 系统上查找快速启动文件的本地副本,我通常这样做:
[root@enterprise ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART
Run Code Online (Sandbox Code Playgroud)
... 或这个:
[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
Run Code Online (Sandbox Code Playgroud)