【问题标题】:shell difference between redirect position重定向位置之间的shell差异
【发布时间】:2016-04-02 08:26:23
【问题描述】:

这两行有什么区别吗?

for i in $(seq 1 10); do echo $i - `date`; sleep 1; done >> /tmp/output.txt

for i in $(seq 1 10); do echo $i - `date` >> /tmp/output.txt ; sleep 1; done

因为Robert told me 第一个只在for循环之外进行I/O OP。

但是,如果我输入 tail -f /tmp/output.txt,则其行为方式完全相同。

【问题讨论】:

    标签: linux bash shell io-redirection


    【解决方案1】:

    还有一个没有提到的重要区别:>> 每次都会打开文件进行写入。这会严重影响性能。

    此外,如果/tmp/output.txt 在循环运行时被删除,echo ... >> /tmp/output.txt 将使用新内容重新创建文件,而for ... done >> /tmp/output.txt 将继续向同一文件添加数据。

    记住这一点很重要,尤其是在我们处理硬链接或临时文件时(通常,我们会在创建临时文件后立即取消链接,以避免在 Bash 脚本意外退出时产生陈旧文件)。

    【讨论】:

      【解决方案2】:

      如果他们成功了,他们也会这样做。但是,如果它们因某种原因失败,则可能存在显着差异。

      第一个:

      for ...; do
         # things
      done >> file
      

      这将在循环完成后重定向到文件。但是,只要 Bash 决定刷新缓冲区,它就可能发生。

      想象一下在第 3 次迭代后发生了故障:您无法判断文件中存储的内容。

      第二个:

      for ...; do
         # things >> file
      done
      

      这将在每次迭代时重定向到文件。

      想象一下在第 3 次迭代后出现故障:您确定前两个循环已正确存储在文件中。

      来自How to redirect output from an infinite-loop program

      如果您的程序使用标准输出函数(例如putsprintf 和来自 C 语言中的 stdio.h、C++ 中的 cout << …print 的朋友 在许多高级语言中),那么它的输出是 buffered: 字符累积在称为缓冲区的内存区域中;什么时候 缓冲区中的数据太多,缓冲区的内容是 打印(它被“刷新”)并且缓冲区变空(准备好 再次填充)。如果你的程序没有产生太多的输出,它可能不会 已经填满了它的缓冲区。

      另外,来自the answer you link

      将重定向操作符放在循环中会使循环加倍 写入 500000 行时的性能(在我的系统上)。

      这是有道理的:如果您必须在每个循环上刷新,这比让 Bash 在觉得方便时刷新要花费更多的时间。一次写五行比一次写一行更容易。

      【讨论】:

      • 谢谢。我怎么知道 Bash 什么时候决定刷新它的缓冲区?例如,我可以强制它每 5/100 个循环刷新一次吗?
      • @Bast 这是一件非常敏感的事情,需要您自己重写循环定义。从Force flushing of output to a file while bash script is still running bash 本身永远不会真正将任何输出写入您的日志文件。相反,它作为脚本的一部分调用的命令将各自单独写入输出并在需要时刷新。所以你的问题实际上是如何强制 bash 脚本中的命令刷新,这取决于它们是什么
      猜你喜欢
      • 2014-04-05
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多