Силовая линия-буферизация stdout при трубопроводе к тройнику

как правило, stdout линия-буфер. Другими словами, пока ваша printf аргумент заканчивается новой строкой, вы можете ожидать, что строка будет напечатана мгновенно. Это не выполняется при использовании канала для перенаправления на tee.

у меня есть программа на C++, a, который выводит строки, всегда \n-прекращено, в stdout.

когда он запускается сам по себе (./a), все печатает правильно и в нужное время, как ожидается. Однако, если я трубу его к tee (./a | tee output.txt), он ничего не печатает, пока не завершит работу, что побеждает цель использования tee.

я знаю, что я мог бы исправить это путем добавления fflush(stdout) после каждой операции печати в программе на C++. Но есть ли более чистый и простой способ? Есть ли команда, которую я могу запустить, например, force stdout быть line-buffered, даже при использовании трубы?

5 ответов


попробовать unbuffer который является частью expect пакета. Возможно, он уже есть в вашей системе.


вы можете попробовать stdbuf

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

(большая) часть man-страницы:

  -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 on tee, вы запускаете его на a, поэтому это не должно повлиять на вас, если вы не установите буферизацию С aС источником.

и stdbuf is не POSIX, но часть GNU-coreutils.


вы также можете попробовать выполнить команду в псевдо-терминале, используя script команда (которая должна обеспечивать буферизованный вывод строки в канал)!

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

имейте в виду script команда не распространяет обратно состояние выхода обернутой команды.


вы можете использовать setlinebuf из stdio.h.

setlinebuf(stdout);

это должно изменить буферизацию на "Line buffered".

Если вам нужна большая гибкость, вы можете использовать setvbuf.


Если вы используете классы потока C++ вместо этого, каждый std::endl is неявный флеш. Используя печать в стиле C, я думаю, что метод, который вы предложили (fflush()) - единственный способ.