Принудительная буферизация stdout при подключении к тройнику
Обычно, stdout
является буферизованной строкой. Другими словами, пока ваш printf
Аргумент заканчивается новой строкой, вы можете ожидать, что строка будет напечатана мгновенно. Это не похоже на удержание при использовании канала для перенаправления на tee
,
У меня есть программа на C++, a
всегда выводит строки \n
-определено, чтобы stdout
,
Когда он запускается сам по себе (./a
), все печатается правильно и в нужное время, как и ожидалось. Однако, если я передам это tee
(./a | tee output.txt
), он ничего не печатает, пока не выйдет, что противоречит цели использования tee
,
Я знаю, что я мог бы это исправить, добавив fflush(stdout)
после каждой операции печати в программе C++. Но есть ли чище, проще? Например, есть ли команда, которую я могу запустить stdout
быть буферизованным, даже при использовании канала?
7 ответов
Пытаться unbuffer
которая является частью expect
пакет. Возможно, он уже есть в вашей системе.
В вашем случае вы бы использовали это так:
./a | unbuffer -p tee output.txt
(-p
предназначен для конвейерного режима, когда небуфер читает из стандартного ввода и передает его команде в остальных аргументах)
Ты можешь попробовать 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.
Вы можете использовать setlinebuf из stdio.h.
setlinebuf(stdout);
Это должно изменить буферизацию на "буферизованную строку".
Если вам нужна большая гибкость, вы можете использовать setvbuf.
Вы также можете попытаться выполнить свою команду в псевдо-терминале, используя script
команда (которая должна принудительно выводить буферизованный вывод в канал)!
script -q /dev/null ./a | tee output.txt # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt # Linux
Быть в курсе script
Команда не передает обратно статус завершения упакованной команды.
В unbuffer
команда из expect
пакет в Dennis Williamson ответ не сработал для меня так, как он был представлен.
Вместо того, чтобы использовать:
./a | unbuffer -p tee output.txt
Пришлось использовать:
unbuffer -p ./a | tee output.txt
(
-p
для режима конвейера, в котором unbuffer читает из stdin и передает его команде в остальных аргументах)
В expect
пакет можно установить на:
- MSYS2 с
pacman -S expected
- Mac OS с
brewinstall expected
Если вместо этого вы используете потоковые классы C++, каждый std::endl
неявный флеш. Используя печать в стиле C, я думаю, что метод, который вы предложили (fflush()
) это единственный способ.
ИМО лучший ответgrep
х--line-buffer
вариант, как указано здесь:
/questions/15442881/detektoryi-utechki-pamyati-dlya-c/15442899#15442899