来自Unix 电动工具,第三版:不要删除文件,而是清空它部分:
如果活动进程打开了该文件(对于日志文件来说并不罕见),则删除该文件并创建新文件不会影响日志记录程序;那些消息将继续访问不再链接的文件。清空文件不会破坏关联,因此它会清除文件而不会影响日志记录程序。
(强调我的)
我不明白为什么程序会继续记录已删除的文件。是因为文件描述符条目没有从进程表中删除吗?
答案1
当您删除文件时,您实际上删除了该文件(inode)的链接。如果有人已经打开了该文件,他们就可以保留他们拥有的文件描述符。该文件保留在磁盘上,占用空间,如果您有权访问该文件,则可以对其进行写入和读取。
这unlink
功能POSIX 定义了此行为:
当文件的链接计数变为0并且没有进程打开该文件时,该文件占用的空间将被释放,并且该文件将不再可访问。如果一个或多个进程在删除最后一个链接时打开了该文件,则应在 unlink() 返回之前删除该链接,但是文件内容的删除应推迟到所有对该文件的引用都已关闭为止。
这条建议是因为这种行为。守护进程将打开该文件,并且不会注意到该文件已被删除(除非它专门监视该文件,但这种情况并不常见)。它会继续愉快地写入它拥有的现有文件描述符:您将继续占用磁盘上的(更多)空间,但您将无法看到它写入的任何消息,所以您真的处于最糟糕的情况两个世界的。如果您将文件截断为零长度,则空间将立即释放,并且任何新消息都将附加在文件的新末尾,您可以在其中看到它们。
最终,当守护进程终止或close
文件,空间将被释放。没有新人可以同时打开该文件(除了通过系统特定的反射接口,例如Linux的/proc/x/fd/...
)。它还保证:
如果文件的链接计数为0,则当与该文件关联的所有文件描述符都关闭时,该文件占用的空间将被释放,并且该文件将不再可访问。
因此,您不会永久丢失磁盘空间,但删除文件不会获得任何好处,并且无法访问新邮件。
答案2
确切地。
文件是三部分的。
- 内容,即字节的平面数组,写入磁盘上的某个位置或即时生成。
- 这索引节点, 或者索引节点简而言之,它是内核填充和使用的数据结构。它包含有关文件的所有元数据(大小、权限等),以及指向文件内容位置的指针。
- 一个或多个目录条目,它们是位置,操纵为路径就像
/home/user/personal_file
,它充当句柄,通过它您可以使用文件、修改其内容、更改其元数据等。
当您打开文件时,您将路径提供给操作系统,它会直接返回索引节点的句柄。使用这个称为文件描述符的句柄,您可以根据需要(或至少在操作系统允许的情况下)操作文件。
你永远不能直接删除一个inode,你必须给出一个小路向操作系统要求删除。因此,当您要删除文件时,只需删除目录条目即可。如果该文件还有其他目录项,它将继续可访问,即使没有,它的 inode 也不会被删除,同时仍然有文件描述符指向它。 @MichaelHomer 的回答在这个特定主题上更具技术性和更详细。
答案3
其他两个答案很好地解释了这个问题 - 文件不会被“删除”,直到所有目录链接到它和所有打开的文件描述符都消失了。
为了避免这种情况,使用它是一个好习惯
> /var/log/bigfile
代替
rm -f /var/log/bigfile
因为这只是将内容重置为 0 字节而不是删除它,并且您仍然可以看到写入的内容。
如果您删除了该文件,并且在具有 /proc/fd 文件系统的 Linux 上,您仍然可以使用
> /proc/12345/fd/3
将文件的内容清零(假设 12345 是您的进程 ID,3 是大文件的 fd 号)。如果您的磁盘已满并且由于某种原因您无法终止写入日志文件的进程,这可能会成为您的救星。