如何使任何 shell 命令的输出无缓冲?

Posted

技术标签:

【中文标题】如何使任何 shell 命令的输出无缓冲?【英文标题】:How to make output of any shell command unbuffered? 【发布时间】:2011-03-28 19:04:25 【问题描述】:

有没有办法在没有输出缓冲的情况下运行 shell 命令?

例如,hexdump file | ./my_script 只会将来自 hexdump 的输入以缓冲块的形式传递给 my_script,而不是逐行传递。

其实我想知道一个通​​用的解决方案如何使任何命令不缓冲?

【问题讨论】:

更多赞成的问题unix.stackexchange.com/questions/25372 或许也可以看看***.com/questions/7161821/… 【参考方案1】:

试试stdbuf,它包含在 GNU coreutils 中,因此几乎可以用于任何 Linux 发行版。这会将输入、输出和错误的缓冲区长度设置为零:

stdbuf -i0 -o0 -e0 command

【讨论】:

这对我来说比unbuffer 效果更好。 stdbuf 传递了任何信号(在我的情况下为 SIGUSR2)我发送给它到 command(这是我想要发生的),而 unbuffer 似乎不想这样做。 stdbuf 使用上述 LD_PRELOAD 技巧之一来执行此操作,因此不适用于静态链接或 setuid 可执行文件。请参阅此问题进行讨论:***.com/questions/13644024/… 我发现这非常有用,但有限,因为它不会隐式运行脚本。但是,stdbuf -o0 bash 运行了一个完整的会话,其中包含我所有可用的脚本和别名,并且在任何命令上都没有输出缓冲,这正是我想要的。缓冲当然会在退出此bash 实例时恢复。我正在使用 Ubuntu 16.04。 我非常喜欢这个,我把它放在我的 .bash_profile 中。 if [[ "$0" == "-bash" ]]; then exec /usr/bin/stdbuf -i0 -oL -eL /bin/bash -l; fi exec 模式为我工作,用于将输出发送到日志文件,所有输出行都缓冲而不是完全禁用缓冲:exec > >(stdbuf -i0 -oL -eL awk 'print strftime("%Y-%m-%d %H:%M:%S"), $0 ' | stdbuf -i0 -oL -eL tee "$LOGFILE") 2>&1【参考方案2】:

expect 包中的命令 unbuffer 禁用输出缓冲:Ubuntu Manpage: unbuffer - unbuffer output

示例用法:

unbuffer hexdump file | ./my_script

【讨论】:

unbuffer 似乎合并了命令的标准输出和标准错误......(!) @olejorgenb 是的,它合并了stdout和stderr,这是设计使然:unbuffer使用expect,并且expect在人机交互中模拟人类,人类看不到输出是否是标准输出或标准错误。【参考方案3】:

AFAIK,如果没有丑陋的黑客,你就无法做到这一点。写入管道(或从中读取)会自动打开完全缓冲,您对此无能为力:-(。“行缓冲”(这是您想要的)仅在读/写终端时使用。丑陋的黑客正是这样做的:他们将程序连接到伪终端,以便管道中的其他工具以行缓冲模式从该终端读取/写入。这里描述了整个问题:

http://www.pixelbeat.org/programming/stdio_buffering/

该页面还有一些建议(前面提到的“丑陋黑客”)做什么,即使用unbuffer 或使用LD_PRELOAD 拉一些技巧。

【讨论】:

谢谢。我以前从未听说过伪终端。【参考方案4】:

您还可以使用script 命令将hexdump 的输出设为行缓冲(hexdump 将在伪终端中运行,这会欺骗hexdump 使其认为将其标准输出写入终端,并且不是管道)。

# cf. http://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe/
stty -echo -onlcr
script -q /dev/null hexdump file | ./my_script         # FreeBSD, Mac OS X
script -q -c "hexdump file" /dev/null | ./my_script    # Linux
stty echo onlcr

【讨论】:

我使用了-f参数来刷新,不确定是否有必要,但确实有效。 在我的例子中,stdbuf 失败了,但脚本就像一个魅力。程序在通过管道传输到tee 时缓冲输出,但在终端中运行时不缓冲。所以,脚本有效!谢谢! 非常聪明的解决方案,而且有效!!谢谢你。 :微笑: 只有一个问题:每个 scriptman 页面由 this 引用,“某些交互式命令,例如 vi(1),在打字稿文件中创建垃圾。脚本最适用于不操纵屏幕的命令,其结果旨在模拟硬拷贝终端。”【参考方案5】:

应该使用 grep 或 egrep "--line-buffered" 选项来解决这个问题。无需其他工具。

【讨论】:

以上是关于如何使任何 shell 命令的输出无缓冲?的主要内容,如果未能解决你的问题,请参考以下文章

PySpark shell 命令不产生任何输出

将 shell 命令的输出插入 emacs 缓冲区

如何在当前 shell 中执行命令的输出?

如何在当前shell中执行命令的输出?

stdout和stderr标准输出的区别

如何获取无缓冲通道中的元素数量