Línea de fuerza-buffering de stdout cuando tubería a tee


Normalmente, stdout es un búfer de línea. En otras palabras, siempre y cuando su argumento printf termine con una nueva línea, puede esperar que la línea se imprima instantáneamente. Esto no parece mantenerse cuando se usa una tubería para redirigir a tee.

Tengo un programa C++, a, que produce cadenas, siempre \n terminadas, a stdout.

Cuando se ejecuta por sí mismo (./a), todo se imprime correctamente y en el momento adecuado, como se esperaba. Sin embargo, si lo canalizo tee (./a | tee output.txt), no imprime cualquier cosa hasta que se detenga, lo que frustra el propósito de usar tee.

Sé que podría arreglarlo agregando un fflush(stdout) después de cada operación de impresión en el programa C++. ¿Pero hay una manera más limpia y fácil? ¿Hay algún comando que pueda ejecutar, por ejemplo, que obligue a stdout a tener un búfer de línea, incluso cuando use una tubería?

Author: RzR, 2012-07-05

5 answers

Pruebe unbuffer que es parte de la expect paquete. Es posible que ya lo tenga en su sistema.

 31
Author: Dennis Williamson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-05 02:50:35

Puedes probar stdbuf

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

(grande) parte de la página de manual:

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

Tenga esto en cuenta, sin embargo:

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.

No estás ejecutando stdbuf en tee, lo estás ejecutando en a, por lo que esto no debería afectarte, a menos que establezcas el búfer de los flujos de a en la fuente de a.

También, stdbufes no POSIX, sino parte de GNU-coreutils.

 83
Author: c00kiemon5ter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-05 02:10:44

También puede intentar ejecutar su comando en un pseudo-terminal usando el comando script (que debería imponer la salida de búfer de línea a la tubería)!

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

Tenga en cuenta que el comando script no propaga el estado de salida del comando envuelto.

 24
Author: jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 05:45:26

Puede usar setlinebuf desde stdio.h.

setlinebuf(stdout);

Esto debería cambiar el buffering a "line buffered".

Si necesita más flexibilidad puede usar setvbuf.

 13
Author: Denys Rtveliashvili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-14 14:46:50

Si utiliza las clases de flujo de C++ en su lugar, cada std::endl es un color implícito. Usando la impresión de estilo C, creo que el método que sugirió (fflush()) es la única manera.

 1
Author: Kevin Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-05 03:12:29