为什么当我重命名或移动目标文件时 tar 仍能继续运行

为什么当我重命名或移动目标文件时 tar 仍能继续运行

我当时正在使用 tar (-cvJf) 运行一个长时间的备份,在备份运行时清理文件夹时没有注意,并重命名了目标文件(使用 mv)。我以为我搞砸了 tar 进程,但令我惊讶的是,它仍在运行,新文件仍在增长。之后文件看起来没问题,所以我运行了恢复来确认所有位都在它们应该在的位置,确实如此。

我的问题是:

  • 这是如何/为什么起作用的?
  • 这是 tar 特有的功能吗?
  • 这是文件系统特定的功能(ext4)吗?
  • 这是发行版特有的功能吗(我正在运行 Ubuntu 18.04.2)?
  • 将文件移动到不同文件夹时,它似乎也能正常工作。我在其他挂载点上没有足够的可用空间来跨挂载点尝试此操作,但想知道可以将其推到多远?

我确信有一个术语可以描述这种现象,但尝试用谷歌搜索这种效果却给了我很多不相关的材料。

答案1

这是 ext4 和 Linux 中其他文件系统的功能。

在此类文件系统中,文件由其 inode 编号标识。Inode 是一种指向数据块和与文件相关的某些元数据(例如权限)的结构。这不包括名称或路径。

当我们说文件foo属于某个目录时,这意味着foo该目录内有一个具有该名称的目录条目,因此该条目指向某个 inode。

这种方法让我们无需付出额外努力即可获得硬链接。可以添加指向同一 inode 的另一个条目(可能使用其他名称,位于同一目录或另一个目录中)。所有此类条目都是相等的,无法分辨哪个是“原始条目”。从技术上讲,在单个文件系统中将文件从一个目录移动到另一个目录是通过在目标目录中创建硬链接(条目)然后删除源目录中的条目来完成的。

当你将路径传递/some/path/to/foo给程序并尝试打开文件时,内核会读取目录/some/path/to/,找到foo条目并了解路径指向哪个 inode(注意,它需要读取/以了解some/,然后读取some/以了解等等path/;比较这个问题)。该程序获得一个文件描述符,该描述符标识某某文件系统上的某某 inode。

此时程序可能会丢弃有关路径的信息。只要它持有描述符,它就可以访问该文件。

我以为我已经破坏了 tar 进程,但令我惊讶的是它仍在运行并且新文件仍在增长。

它是具有相同 inode 的相同文件。您创建了一条指向该文件的附加路径并销毁了原始路径。tar获得该文件的访问权限后,它不再需要这些路径。

如果tar记住了路径并(无论出于什么原因)尝试使用(现在不存在的)路径第二次打开文件,那么它将失败。事实并非如此。但是,其他工具可能会这样做(例如,某些tail支持--follow=name--follow=descriptor选项的实现)。


基于 inode 的文件系统的另一个特点是能够删除(取消链接)正在使用的文件。可以删除指向特定 inode 的所有硬链接(路径、名称),但如果文件处于打开状态,则它仍将占用空间并能够增长。描述符保持有效,程序继续使用该文件。当所有程序关闭文件并且不再使用时,内核会通知文件系统并释放空间。如果出现问题(例如硬重置),fsck应检测并修复孤儿 inode

这可能会导致以下情况:删除文件不会释放磁盘空间。另一方面,您可以创建一个临时文件,打开它,取消链接,但仍使用它。这在 Linux 中很有用,也是意料之中的,以至于该行为是针对不支持该功能的文件系统进行模拟的

我在其他挂载点上没有足够的可用空间来跨挂载点尝试此操作,但想知道可以将其推到多远

将文件移动到另一个文件系统是通过复制,然后删除(取消链接)原始文件来完成的。您可以复制文件(即按顺序读取文件并将数据写入其他地方)。如果您在tar结束之前取消链接原始文件,则tar仍可使用它(在原始文件系统上),因为这是它打开的文件。

在您的案例中,您可能会在副本中得到截断的数据。如果复制过程在tar仍在运行时到达原始文件的末尾,它会认为复制已完成,尽管事实上tar即将附加到文件中(复制过程不知道,也不关心)。有恢复原始文件的方法但是如果您什么都不做并让它tar完成,它将关闭描述符,文件将变得无法访问,其数据将被标记为可能被覆盖的空白空间。

复制正在使用的文件时的另一个常见问题是一致性。tar顺序写入文件,因此即使您只复制文件的初始部分,您仍然可以提取一些数据。但想象一下一个不按顺序查找和修改文件的工具。它可能会改变您已经复制的片段和您即将复制的片段。结果不仅可能被截断,还可能不连贯(有趣的类比:全景失败)。

答案2

因为在 Unix 文件系统(ext4 和其他系统)中,实际的文件是一个“inode”(它的标识符只是一个唯一的数字),而你在它上面放置的路径/名称只是一种访问它的便捷方式。

当应用程序打开文件时,它实际上打开了 inode,除非它稍后尝试通过名称访问文件(例如重命名),否则它不会注意到您是否重命名/移动它。

这也是为什么你可以有“硬链接”的原因:它们只是有多个指向同一 inode 的路径/名称。当最后一个名称消失(rmunlink)时,inode 文件将返回到可用空间。

应用程序也不会注意到文件已被删除...如果您rm在写入文件时对其进行操作,则文件会继续增长。只有当应用程序关闭它时,它才会被删除,这就是为什么有时删除“实时”应用程序日志不会释放任何磁盘空间的原因。

如果您想探索:ls -i为您提供文件的 inode 编号,并ls -l告诉您该文件的 inode 有多少个链接。

相关内容