【问题标题】:Bash tail command and multiple pipesBash tail 命令和多个管道
【发布时间】:2019-06-14 22:06:04
【问题描述】:

我目前遇到了命令问题

while sleep 0.3; do echo "1"; done | tail -n +3 | grep --line-buffered "1"

我想要一个如下所示的输出:

[nothing during 0.6s]
1
1
...

但有:

[nothing forever]

我找到了this question 并阅读了this blog post,但由于--line-buffered 选项设置为grep,我认为这不是缓冲问题。我的研究并没有让我找到其他解决方案,我希望我没有遗漏一些明显的东西。

如果很重要,我正在使用zsh 5.7.1 (x86_64-pc-linux-gnu)

【问题讨论】:

  • tail 的输出被缓冲。
  • --line-buffered 选项仅在您将grep 的输出传送到需要立即查看的内容时才有用。由于您没有管道输出,因此在这里没有帮助。

标签: bash pipe


【解决方案1】:

正如 Barmar 在 cmets 中提到的,这被 4KB stdio buffer 所吞噬。您可以使用unbuffer -p 来避免它:

while sleep 0.3; do echo "1"; done | unbuffer -p tail -n +3 | grep 1

或者您也可以在行缓冲模式下使用stdbuf

while sleep 0.3; do echo "1"; done | stdbuf -oL tail -n +3 | grep 1

【讨论】:

  • 它解决了我的问题。我应该完全阅读博客文章,而不是在其中快速搜索信息。谢谢!
  • 澄清一下,数据保存在 4k glibc stdio 输出缓冲区中,而不是 64k 管道缓冲区中
  • @thatotherguy 谢谢,重新措辞。
【解决方案2】:

根据实际情况,您可能可以通过使用一个更强大的工具(例如awk)来避免问题(由从tailgrep 的管道引起):

while sleep 0.3; do echo "1"; done | awk 'NR > 2 && /1/'

当然,如果您需要将awk 的输出通过管道传输到其他内容中,那么您将再次遇到同样的问题。但如果您的awk 版本支持它,您可以显式刷新输出:

while sleep 0.3; do echo "1"; done | awk 'NR > 2 && /1/ {print $0; fflush()}' | | while read x; do echo "read '$x'"; done

...或者可能在awk 上使用unbuffer -pstdbuf -oL(请参阅@JeffBowman 的回答),如果你有这些(我没有,所以我无法测试它们)。

【讨论】:

  • 我在问题中写的命令被简化了,主要是因为我使用的一些工具是非标准的,我不希望人们为了测试命令而必须安装额外的工具。整个命令需要 4 个管道,最后一个是 while read ... 命令。不过,这对其他人来说可能是一个有效的解决方案,谢谢!
  • @Nelimee 哈哈,我在awk 中找到了一种让它工作的方法(使用另一个管道)。可能仍然与您的情况无关,但它可能对其他人有用。
猜你喜欢
  • 2016-06-18
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多