Force line-buffering of stdout when piping to tee

蹲街弑〆低调 提交于 2019-11-26 06:48:57
Dennis Williamson

Try unbuffer which is part of the expect package. You may already have it on your system.

In your case you would use it like this:

./a | unbuffer -p tee output.txt

(-p is for pipeline mode where unbuffer reads from stdin and passes it to the command in the rest of the arguments)

you can try stdbuf

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

(big) part of the man page:

  -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.

keep this in mind, though:

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.

you are not running stdbuf on tee, you're running it on a, so this shouldn't affect you, unless you set the buffering of a's streams in a's source.

Also, stdbuf is not POSIX, but part of GNU-coreutils.

jon

You may also try to execute your command in a pseudo-terminal using the script command (which should enforce line-buffered output to the pipe)!

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

Be aware the script command does not propagate back the exit status of the wrapped command.

You can use setlinebuf from stdio.h.

setlinebuf(stdout);

This should change the buffering to "line buffered".

If you need more flexibility you can use setvbuf.

If you use the C++ stream classes instead, every std::endl is an implicit flush. Using C-style printing, I think the method you suggested (fflush()) is the only way.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!