执行过程中删除 nohup 文件

14

我做了以下事情:

nohup find / &

rm nohup.out

奇怪的是,nohup -command 命令继续运行。我等待新文件被创建。但出乎意料的是,并没有这样的文件。命令的标准输出(stdout)去哪了?

4个回答

13

在 UNIX 中删除一个文件会执行两个操作:

  • 删除其对应的目录项。
  • 如果没有进程打开它,也没有其他目录项指向它(硬链接),则释放该文件占据的空间。

您的 nohup 进程仍然可以愉快地写入曾经被称为 nohup.out 的文件,但现在只是该进程内的一个文件描述符,无需实际文件名。

您甚至可以让另一个进程创建一个 nohup.out 文件,它不会影响第一个进程。

当所有硬链接都消失,且所有进程已经关闭该文件时,磁盘空间才会被回收。


如果可以将inode的位置更改为/dev/null,我认为也可以将其更改为其他位置。假设我想要每5秒钟将find命令的stdout输出到不同的位置。我知道我可以在每个步骤中创建一个新的硬链接,并始终删除最后一个链接。但是,我无法理解这个过程。如何确保每5秒钟的stdout具有不同的inode编号?如何确保异步处理以确保记录所有内容? - Léo Léopold Hertz 준영
那个第一句话有点令人困惑,@SQ,我不认为你理解inode是什么——它实际上只是底层文件的ID(数据,而不是目录项)。通过更改为/dev/null,你是指“find / >/dev/null”吗?find只是将输出发送到从shell继承的文件描述符。使用重定向,shell将stdout附加到文件(或设备驱动程序,如/dev/null),然后fork/execs find,find将使用该stdout描述符。find本身不知道它正在写入哪个文件,只知道一个描述符。因此,它不会重新创建目录项,因为它的文件仍然存在。 - paxdiablo
3
@SimpleQuestions: 很少有程序每次写入时都打开一个文件,特别是当它们正在写入标准输出时更不会这样做。它们只需继续使用一个已打开的文件描述符。一旦你的程序开始向某个文件写入,它就会持续这样做。你无法通过(重新)移动文件来更改它写入的文件。 - Jonathan Leffler
嘿,这就是我说的,只不过你的用的是易懂的英语 :-) - paxdiablo
2
如果将来您想在进程正在写入日志文件时截断它,请使用以下命令: cat /dev/null > nohup.out - teambob

10
如果您删除nohup.out文件,该句柄将丢失并且它只会写入文件描述符,但如果您想清理nohup.out文件,只需运行以下命令:
true > nohup.out

它将删除文件的内容,但不会删除文件本身。


程序能够正常工作,但当应用程序写入更多数据时,我只看到十六进制数字: 0000 0000 0000 0000 0000 0000 0000 0000 最后几位数字不同于0。 - Davide
不应该出现这种情况。很可能是 nohup 文件损坏了。你能告诉我你是如何启动 nohup 命令的吗? - Saad Saadi
当然可以!"java -jar MyApp.jar > nohup.out 2>&1 &" - Davide

3

这是Unix系统的标准行为。

当你删除文件时,文件系统中的最后一个链接被删除了,但是文件仍然打开,因此find(在这种情况下)的输出被写入内核缓冲池中的磁盘块,可能甚至写入磁盘。但是该文件没有名称。当find退出时,没有进程或文件(inode)引用该文件,因此释放了空间。这是创建程序退出时将消失的临时文件的一种方法-通过打开文件,然后删除它。(这假设您不需要文件名;如果您需要临时文件的名称,则此技术将无法使用。)


由于rm命令删除了最后一个链接,数据仍然存在于磁盘上,除非被覆盖。不知道最后一个链接的情况下找到数据的概率是多少? - Léo Léopold Hertz 준영
概率为零 - 除非您去探索原始设备。该文件占用空间(df将报告其为“正在使用”)。但是,没有名称可以访问它。理论上,原始进程可以读取数据(以及写入数据);当然,“find”不会这样做。 - Jonathan Leffler

2
cat /dev/null > nohup.out

来自这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接