管道到三通时强制线缓冲标准输出

时间:2012-07-05 01:58:44

标签: unix buffer pipe stdout tee

通常,stdout是行缓冲的。换句话说,只要您的printf参数以换行符结尾,您就可以立即打印该行。使用管道重定向到tee时,这似乎不成立。

我有一个C ++程序a,它将\n - 终止的字符串输出到stdout

当它自己运行时(./a),所有内容都会按照预期在正确的时间正确打印。但是,如果我将其管道传输到tee./a | tee output.txt),则在退出之前不会打印任何内容,从而无法使用tee

我知道我可以通过在C ++程序中的每次打印操作后添加fflush(stdout)来修复它。但是有更清洁,更简单的方法吗?例如,是否存在可以运行的命令,即使使用管道,也会强制stdout进行行缓冲?

6 个答案:

答案 0 :(得分:108)

您可以尝试stdbuf

$ stdbuf -o 0 ./a | tee output.txt

(大)手册页的一部分:

  -i, --input=MODE   adjust standard input stream buffering
  -o, --output=MODE  adjust standard output stream buffering
  -e, --error=MODE   adjust standard error stream buffering

If MODE is 'L' the corresponding stream will be line buffered.
This option is invalid with standard input.

If MODE is '0' the corresponding stream will be unbuffered.

Otherwise MODE is a number which may be followed by one of the following:
KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.
In this case the corresponding stream will be fully buffered with the buffer
size set to MODE bytes.

请记住这一点:

NOTE: If COMMAND adjusts the buffering of its standard streams ('tee' does
for e.g.) then that will override corresponding settings changed by 'stdbuf'.
Also some filters (like 'dd' and 'cat' etc.) dont use streams for I/O,
and are thus unaffected by 'stdbuf' settings.

你没有在stdbuf上运行tee,而是在a上运行它,所以这不应该影响你,除非你设置a的缓冲a来源的流。

此外,stdbuf POSIX,但是GNU-coreutils的一部分。

答案 1 :(得分:44)

尝试unbuffer这是expect包的一部分。您可能已经在系统上拥有它。

在你的情况下,你会像这样使用它:

./a | unbuffer -p tee output.txt

-p用于管道模式,其中unbuffer从stdin读取并将其传递给其余参数中的命令)

答案 2 :(得分:26)

您也可以尝试使用script命令在伪终端中执行命令(这应该强制执行到管道的行缓冲输出)!

script -q /dev/null ./a | tee output.txt     # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt   # Linux

请注意script命令不会传播包装命令的退出状态。

答案 3 :(得分:18)

您可以使用stdio.h中的setlinebuf。

setlinebuf(stdout);

这应该将缓冲更改为" line buffered"。

如果您需要更多灵活性,可以使用setvbuf。

答案 4 :(得分:2)

如果您使用C ++流类,则每个std::endl 都是隐式刷新。使用C风格的打印,我认为你建议的方法(fflush())是唯一的方法。

答案 5 :(得分:1)

unbuffer包中的expect软件包中的@Paused until further notice命令对我的显示方式无效。

代替使用:

./a | unbuffer -p tee output.txt

我必须使用:

unbuffer -p ./a | tee output.txt

({-p用于管道模式,其中unbuffer从stdin读取并将其传递给其余参数中的命令)

expect软件包可以安装在:

  1. 带有pacman -S expected的MSYS2
  2. 具有brew install expected的Mac OS
相关问题