【发布时间】:2018-04-14 14:21:10
【问题描述】:
我在 bash 脚本中有一个 while 循环:
例子:
while read LINE
do
echo $LINE >> $log_file
done < ./sample_file
我的问题是为什么当我在脚本运行时删除 sample_file 时,循环并没有结束,而且我看到 log_file 正在更新?没有输入时循环如何继续?
【问题讨论】:
标签: bash while-loop diskcache
我在 bash 脚本中有一个 while 循环:
例子:
while read LINE
do
echo $LINE >> $log_file
done < ./sample_file
我的问题是为什么当我在脚本运行时删除 sample_file 时,循环并没有结束,而且我看到 log_file 正在更新?没有输入时循环如何继续?
【问题讨论】:
标签: bash while-loop diskcache
请参阅"Why file is accessible after deleting in unix?",以获得对您在此处观察到的内容的出色解释。
总之……
底层 rm 和任何其他可能会删除文件的命令 有系统调用unlink。它被称为取消链接,而不是删除或 deletefile 或任何类似的东西,因为它不会删除文件。它 删除作为关联的链接(又名目录条目) 在文件和目录中的名称之间。
您可以使用函数truncate 来销毁实际内容(或shred,如果您需要更安全),这将立即停止示例循环的执行。
【讨论】:
在 unix 中,直到文件的最后一个目录条目被删除(例如 rm)并且最后一个打开的文件句柄被关闭,文件才真正被删除。有关更多信息,请参阅this question(尤其是 MarkR 的回答)。对于您的脚本,文件作为while read 循环的标准输入打开,直到该循环退出(或关闭其标准输入),rming 文件实际上不会从磁盘上删除它。
如果你愿意,你可以很容易地看到这种效果。打开三个终端窗口。首先,运行命令cat >/tmp/deleteme。第二,运行tail -f /tmp/deleteme。第三,运行其他两个命令后,运行rm /tmp/deleteme。此时,该文件已被取消链接,但cat 和tail 进程都有为其打开的文件句柄,因此它实际上并没有被删除。您可以通过在第一个终端窗口中输入(运行cat)来证明这一点,每次点击返回时,tail 都会看到新行添加到文件中并显示在第二个窗口中。
在您结束这两个命令之前,该文件实际上不会被删除(Control-D 将结束 cat,但您需要 Control-C 来终止 tail)。
【讨论】:
在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个数字。
【讨论】: