我有一个调用两个命令的脚本:
long_running_command | print_progress
印刷品long_running_command
取得了进展,但我对此不满意。我用来print_progress
让它变得更好(即,我在一行中打印进度)。
问题:将管道连接到 stdout 也会激活 4K 缓冲区,因此漂亮的打印程序什么也得不到......什么都没有......什么都没有......一大堆...:)
如何禁用4K
缓冲区long_running_command
(不,我没有源代码)?
答案1
给这只猫剥皮的另一种方法是使用stdbuf
程序,它是 GNU Coreutils 的一部分(FreeBSD 也有自己的)。
stdbuf -i0 -o0 -e0 command
这将完全关闭输入、输出和错误的缓冲。对于某些应用程序,出于性能原因,行缓冲可能更适合:
stdbuf -oL -eL command
请注意,它仅适用于动态链接应用程序的stdio
缓冲(printf()
,fputs()
...),并且仅当该应用程序本身不调整其标准流的缓冲时,尽管这应该涵盖大多数应用程序。
答案2
答案3
对于grep
,sed
您awk
可以强制输出进行行缓冲。您可以使用:
grep --line-buffered
强制输出进行行缓冲。默认情况下,当标准输出是终端时,输出是行缓冲的,否则是块缓冲的。
sed -u
使输出行缓冲。
请参阅此页面了解更多信息: http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html
答案4
如果当输出未到达终端时 libc 修改其缓冲/刷新出现问题,您应该尝试索卡特。您可以在几乎任何类型的 I/O 机制之间创建双向流。其中之一是与伪 tty 对话的分叉程序。
socat EXEC:long_running_command,pty,ctty STDIO
它的作用是
- 创建一个伪 tty
- fork long_running_command 并将 pty 的从属端作为 stdin/stdout
- 在pty的主端和第二个地址(这里是STDIO)之间建立双向流
如果这给出了与 相同的输出long_running_command
,那么您可以继续使用管道。
编辑:哇没有看到无缓冲的答案!好吧,socat 无论如何都是一个很棒的工具,所以我可能会留下这个答案