1

我在 bash 脚本中有一个 while 循环:

例子:

while read LINE
do
echo $LINE >> $log_file
done < ./sample_file

我的问题是为什么当我在脚本运行时删除 sample_file 时,循环并没有结束,而且我看到 log_file 正在更新?没有输入时循环如何继续?

4

3 回答 3

2

在 unix 中,直到文件的最后一个目录条目被删除(例如使用rm关闭它的最后一个打开文件句柄,文件才真正被删除。有关更多信息,请参阅此问题(尤其是 MarkR 的答案)。对于您的脚本,该文件作为循环的标准输入打开while read,并且直到该循环退出(或关闭其标准输入),rm该文件实际上不会将其从磁盘上删除。

如果你愿意,你可以很容易地看到这种效果。打开三个终端窗口。首先,运行命令cat >/tmp/deleteme。第二步,运行tail -f /tmp/deleteme。第三,在运行其他两个命令后,运行rm /tmp/deleteme. 此时,文件已被取消链接,但cattail进程都有打开的文件句柄,因此它实际上并没有被删除。您可以通过在第一个终端窗口(正在运行)中键入来证明这一点cat,每次点击返回时,tail都会看到新行添加到文件中并显示在第二个窗口中。

在您结束这两个命令之前,该文件实际上不会被删除(Control-D will end cat,但您需要 Control-C to kill tail)。

于 2017-11-02T06:56:58.747 回答
2

请参阅“为什么在 unix 中删除后可以访问文件?” 以获得对您在此处观察到的内容的出色解释。

简而言之...

底层 rm 和任何其他可能会删除文件的命令是系统调用 unlink。它被称为取消链接,而不是删除或删除文件或类似的东西,因为它不会删除文件。它删除了一个链接(又名目录条目),该链接是文件和目录中的名称之间的关联。

您可以使用该函数truncate销毁实际内容(或者shred如果您需要更安全),这将立即停止示例循环的执行。

于 2017-11-02T06:59:17.467 回答
0

在shell执行while循环的那一刻,sample_file内容已经被读取,在那之后文件是否存在都没有关系。

测试脚本:

$ cat test.sh 
#!/bin/bash

while read line
do
    echo $line
    sleep 1
done < data_file

测试文件:

$ seq 1 10 > data_file

现在,在一个终端中运行脚本,在另一个终端中,您去删除文件data_file,您仍然会看到脚本打印的 1 到 10 个数字。

于 2017-11-02T06:29:55.027 回答