【问题标题】:Bash commands piped to awk are sometimes buffered通过管道传输到 awk 的 Bash 命令有时会被缓冲
【发布时间】:2018-11-16 07:42:36
【问题描述】:

系统:Linux 4.13.0-43-generic #48~16.04.1-Ubuntu BASH_VERSION='4.3.48(1)-release'

命令:

while sleep 5
do
  date +%T
done | awk -F: '{print $3}'

应该打印“日期”输出的第三个字段(秒),每 5 秒打印一行。问题:awk 仅在管道缓冲区已满时才从管道读取并处理其输入。即当生成超过 4K 的输入时。

awk 替换为 cat 时,按预期每 5 秒打印一行。

这段代码 sn-p 是从一个在其他系统上运行良好的 shell 脚本简化而来的,所以在这个系统中一定有一些关于 bash、awk 及其配置的东西。

简而言之,有没有办法让 awk 在从管道读取数据时表现得像 cat

@Ed Morton:我确实尝试在每次打印后添加 fflush(),但它不起作用——这表明问题出在 awk 的输入上,而不是输出上。 我还尝试添加对 system("date") 的调用,这表明 awk 确实一次获取所有输入行,而不是在生成时立即获取。

对于那些询问的人:

$ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan

compiled limits:
max NF             32767
sprintf buffer      2040

【问题讨论】:

  • 这里的awk版本比bash版本更贴切。也就是说,我根本无法重现这一点——事实上,它不应该是可重现的,因为date 必须在退出之前刷新它的输出。
  • 您能否提供一个 Dockerfile 来重现问题所在?我已经尝试了两个不同的环境,并且这个问题中的代码示例表现正常。
  • 问题可能与您修剪掉的周围代码有关,例如如果您将 awk 输出通过管道传输到另一个命令。无论如何,请尝试在打印后添加对 fflush() 的调用,看看是否有帮助 - {print $3; fflush()}。详情见gnu.org/software/gawk/manual/gawk.html#I_002fO-Functions
  • 当您简化代码时,请确保在简化后对其进行测试。这有助于确保您不会意外移除相关部件。
  • 嗨,它对我有用,我也试过while sleep 5; do date +%T | cut -d: -f3;done

标签: linux bash awk mawk


【解决方案1】:

在试图找出如何让 awk 打印它的版本时,我发现它真的是 mawk,并且它具有以下标志:

 -W interactive -- sets unbuffered writes to stdout and line buffered reads from stdin.
                   Records from stdin are lines regardless of the value of RS.

这似乎解决了问题!

感谢所有回复者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 2018-01-25
    • 2023-01-26
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    相关资源
    最近更新 更多