情况是我们正在运行一个进程,该进程正在以惊人的速度填充日志文件。我知道原因,我可以解决。在此之前,我想在不关闭进程的情况下rm或清空日志文件。
只需执行
rm output.log
即可仅删除对该文件的引用,但它会继续占用磁盘空间,直到该进程终止。更糟:在rm
ing之后,我现在无法找到文件的位置或大小! 我特别指的是基于Linux的操作系统,例如Debian或RHEL。
#1 楼
如果无法终止应用程序,则可以截断而不是删除日志文件来回收空间。如果未在附加模式下打开文件(使用O_APPEND
),则该文件将与下一次应用程序向其写入文件时一样大(尽管前导部分稀疏并且看起来好像包含NUL字节),但是空间将被回收(尽管不适用于Apple OS / X上不支持稀疏文件的HFS +文件系统)。要截断它:
: > /path/to/the/file.log
如果已将其删除,则在Linux上,您仍然可以通过以下方式截断它:
已打开文件的进程,并在其中打开了一个文件描述符(您可以使用
$pid
进行检查。可以做到:如@ user75021所述,: > "/proc/$pid/fd/$fd"
$fd
是一个更好的选项(更可靠,更可移植)(列出的文件少于1个链接)。 或(在Linux上):
lsof -nP | grep '(deleted)'
或者使用
lsof -p "$pid"
查找大的块:调试器使其调用lsof -nP +L1
,然后调用新的zsh
。评论
还有一个截断命令可以更明确地执行相同的操作。
–东武
13年3月20日在9:15
@dotancohen Stephane编辑为包含有关未知pid时如何执行此操作的信息。
–迪迪·科恩(Didi Kohen)
13年3月20日在10:48
@ OlivierDulac,lsof可能是最接近您可以列出打开文件的便携式解决方案的地方。在应用程序脚下关闭fd的调试器方法也应该很容易移植。
–StéphaneChazelas
13年3月20日在13:50
@StephaneChazelas:谢谢。我找到了一种列出所有在每个分区上打开文件的PID的方法:df -k | awk'NR> 1 {print $ NF}'| xargs fuser -Vud(然后轻松地向违规者发送信号以迫使他们释放fd)
–奥利维尔·杜拉克(Olivier Dulac)
13年3月20日在18:56
您也可以使用lsof + L1。在lsof手册页中:“格式为+ L1的规范将选择已取消链接的打开文件。格式为+ aL1
–同步
14-10-23在6:26
#2 楼
在此处查看快速入门:lsof
快速入门我很惊讶没有人提到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系统上查找快速启动文件的本地副本,通常是这样做的:
br />
[root@enterprise ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART
#3 楼
文件系统驱动程序实际上要释放分配的空间,通常只有在释放所有引用该文件的文件描述符后,才会发生这种情况。因此,除非您使应用程序关闭文件,否则您无法真正回收空间。这意味着要么终止它,要么在调试器中“稍微”播放它(例如,关闭文件并确保不再打开/写入该文件,或者打开/dev/null
)。或者您可以破解内核,但是我建议您这样做。在任何情况下都可能仅在关闭文件后才释放)。此行为背后的原因是内核不知道该如何处理数据请求(读写),但是读取是实际上更关键)针对此类文件。
评论
由于Linux在大多数文件系统上都支持稀疏文件,因此行为是明确定义的,并且磁盘驱动程序可以真正释放磁盘空间。我已经对ext3和ext4进行了测试,它的工作方式就像Stephane所写的一样。
– jofel
13年3月20日在10:14
是什么让您说截断文件不会收回预分配的块?截断是为了释放数据,我认为这没有任何歧义。
–StéphaneChazelas
13年3月20日在11:22
文件系统可以保留分配的块以节省以后的时间(尤其是如果文件仍保持打开状态),尤其是在截断之前足够大的情况下。至少XFS似乎正在这样做。
–彼得
13年3月20日在12:53
谢谢彼得。我很高兴您解决本文中的“为什么”。
– dotancohen
13年3月21日在6:09
据我所知,截断打开的文件也确实会回收XFS上的空间。在Linux 4.9上同时测试了普通文件和使用fallocate分配的文件。您能否说明在什么文件系统和条件下截断文件不会回收空间?
–StéphaneChazelas
17年5月3日,11:52
评论
如果知道pid,则可以使用lsof -p谢谢。如何获得所有仍打开的rmed文件的PID?
@donothingsuccessfully lsof报告的“ deleted”标记是特定于Solaris的,实际上仅是Solaris 10或更高版本。 OP未指定他使用的操作系统。 @dotancohen在Solaris上,您可以通过管道传递lsof的输出来搜索已删除的内容,例如lsof | |。 grep“(已删除)”。当没有其他进程打开已删除文件时,内核将释放索引节点和磁盘块。进程没有“处理程序”,可以通过它们通知已从磁盘中删除了一个打开的,基本上是锁定的文件。
@ Johan,lsof | grep'(deleted)'也可以在Linux上使用。在Linux上,可以使用inotify机制(IN_DELETE_SELF事件)通知您文件删除(甚至在/ proc / some-pid / fd之外的任何目录中都没有任何条目的文件)
我创建了一个文件,并在VIM中将其打开,然后在另一个bash进程中对其进行了修剪。然后运行lsof | grep somefile并且它不在其中,即使该文件已在VIM中打开。