如何使任何 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
时缓冲输出,但在终端中运行时不缓冲。所以,脚本有效!谢谢!
非常聪明的解决方案,而且有效!!谢谢你。 :微笑:
只有一个问题:每个 script
的 man
页面由 this 引用,“某些交互式命令,例如 vi(1)
,在打字稿文件中创建垃圾。脚本最适用于不操纵屏幕的命令,其结果旨在模拟硬拷贝终端。”【参考方案5】:
应该使用 grep 或 egrep "--line-buffered" 选项来解决这个问题。无需其他工具。
【讨论】:
以上是关于如何使任何 shell 命令的输出无缓冲?的主要内容,如果未能解决你的问题,请参考以下文章