【问题标题】:bash while loop through a file doesn't end when the file is deleted删除文件时,bash while循环文件不会结束
【发布时间】: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


    【解决方案1】:

    请参阅"Why file is accessible after deleting in unix?",以获得对您在此处观察到的内容的出色解释。

    总之……

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        在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个数字。

        【讨论】:

          猜你喜欢
          • 2012-12-23
          • 2014-10-31
          • 1970-01-01
          • 2021-11-25
          • 2013-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-16
          相关资源
          最近更新 更多