从打开的已删除文件中释放磁盘空间的最佳方法

从打开的已删除文件中释放磁盘空间的最佳方法

您好,我有许多文件已被删除,但由于某种原因,与已删除文件关联的磁盘空间无法使用,直到我明确终止占用磁盘空间的文件的进程

$ lsof /tmp/
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF      NODE NAME
cron     1623 root    5u   REG   0,21        0 395919638 /tmp/tmpfPagTZ4 (deleted)

上面删除的文件占用的磁盘空间会导致问题,例如在尝试使用 Tab 键自动完成文件路径时出现错误bash: cannot create temp file for here-document: No space left on device

但在我运行kill -9 1623该 PID 的空间后,该 PID 的空间被释放,并且我不再收到错误。

我的问题是:

  • 为什么第一次删除文件时没有立即释放该空间?
  • 恢复与已删除文件相关的文件空间的最佳方法是什么?

请让我知道我使用过的任何不正确的术语或与此情况有关的任何其他相关信息。

答案1

在 unice 上,文件名只是指向文件所在内存的指针(索引节点)(可以是硬盘驱动器,甚至是 RAM 支持的文件系统)。每个文件都会记录指向它的链接数量:链接可以是文件名(复数,如果同一个文件有多个硬链接),而且每次打开文件时,进程实际上都会保存到的“链接”同一个空间。

仅当没有剩余链接时,该空间才会被物理释放(因此,不可能到达它)。这是唯一明智的选择:当文件正在使用时,其他人是否无法再访问它并不重要:您正在使用它,直到您关闭它,您仍然可以控制它 - 您甚至不会注意到文件名消失或移动或其他什么。这甚至用于临时文件:某些实现创建一个文件并立即取消链接它,因此它在文件系统中不可见,但创建它的进程正在正常使用它。 Flash插件特别喜欢这种方法:所有下载的视频文件都保持打开状态,但文件系统不显示它们。

所以,答案是,当进程仍然打开文件时,您不应该期望拿回空间。它没有被释放,而是被积极使用。这也是应用程序在使用完文件后应该真正关闭文件的原因之一。在正常使用中,您不应该认为该空间是空闲的,而且这也不应该很常见 - 除了故意取消链接的临时文件之外,实际上不应该有任何您想要的文件考虑未使用,但仍然开放。尝试检查是否有一个进程经常执行此操作,并考虑如何使用它,或者只是寻找更多空间。

答案2

文件将从文件系统中删除,并删除对此 inode 的任何引用。参考可以在磁盘上(链接在任何目录中),并且......来自打开的应用程序。如果删除文件 - 您只会从磁盘中删除引用,但是 - 仍然存在来自应用程序的引用。

您可以通过两种方式“释放”空间:

  1. 如上所述 - 您可以杀死打开文件的应用程序。
  2. 你可以...截断文件。即使删除了:

如果你知道 pid - 看看这个 pid 打开了哪些文件: ls -l /proc/PID/fd 你会在这里看到如下链接:

undefine@uml:~$ ls -l /proc/18596/fd
拉泽姆 0
lrwx------ 1 取消定义 取消定义 64 lut 1 00:06 0 -> /dev/pts/30
lrwx------ 1 取消定义 取消定义 64 lut 1 00:06 1 -> /dev/pts/30
lrwx------ 1 取消定义 取消定义 64 lut 1 00:05 2 -> /dev/pts/30
lr-x----- 1 undefine undefine 64 lut 1 00:06 3 -> /home/undefine/x (已删除)
lr-x----- 1 undefine undefine 64 lut 1 00:06 4 -> anon_inode:inotify

如您所见 - 3 个 fd 被删除。您可以通过命令截断它(例如):

undefine@uml:~$ :>/proc/18596/fd/3
取消定义@uml:~$

请记住,如果应用程序从此文件中读取数据,这对他们来说可能是危险的。但是 - 如果它只是一个日志文件 - 您可以安全地截断它。

答案3

正如其他人所说,lsof可用于列出由于打开的文件描述符而仍在磁盘上的所有已删除文件。然而,这可能是一个很长的清单。以下命令列出了按字节大小升序排列的这些文件:

sudo lsof -F sn0 | tr -d '\000' | grep deleted | sed 's/^[a-z]*\([0-9]*\)n/\1 /' | sort -n

可能有一种更简洁的方法可以做到这一点,但上面的命令对我有用。

答案4

尝试使用以下命令

lsof | grep deleted

然后杀掉被删除文件的pid。

相关内容