165 votes

Forcer la mise en mémoire tampon de la sortie standard lors de la tuyauterie au tee

Généralement, stdout est de ligne-mis en mémoire tampon. En d'autres termes, aussi longtemps que votre printf argument se termine par un saut de ligne, vous pouvez vous attendre à la ligne à imprimer instantanément. Cela ne semble pas tenir lors de l'utilisation d'un tuyau de redirection tee.

J'ai un programme C++, ades sorties des chaînes, toujours \n-terminé, pour stdout.

Lorsqu'il est exécuté par lui-même (./a), tout ce qui s'imprime correctement et au bon moment, comme prévu. Cependant, si je pipe à tee (./a | tee output.txt), il n'a pas d'imprimer quoi que ce soit jusqu'à ce qu'elle se ferme, ce qui est contraire au but de l'utilisation d' tee.

Je sais que je pourrais corriger cela en ajoutant un fflush(stdout) après chaque opération d'impression dans le programme C++. Mais est-il plus propre, la plus facile? Est-il une commande je peux courir, par exemple, ce serait forcer stdout à être en ligne de tampon, même lors de l'utilisation d'un tuyau?

166voto

c00kiemon5ter Points 5561

vous pouvez essayer d' stdbuf

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

(grosse) partie de la page de 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.

gardez cela à l'esprit, cependant:

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.

vous n'êtes pas en cours d'exécution stdbuf sur tee, vous êtes en cours d'exécution sur a,, donc il ne devrait pas avoir pour vous, sauf si vous définissez la mise en mémoire tampon de l' as'flux en a's de la source.

Aussi, stdbuf est pas POSIX, mais une partie de GNU coreutils.

85voto

Dennis Williamson Points 105818

Essayez unbuffer qui fait partie du package expect . Vous l'avez peut-être déjà sur votre système.

33voto

jon Points 71

Vous pouvez également essayer d'exécuter votre commande dans un pseudo-terminal à l'aide de la commande script (qui devrait appliquer la sortie tamponnée à la ligne dans le canal)!

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

3voto

Kevin Grant Points 3208

Si vous utilisez plutôt les classes de flux C ++, chaque std::endl est un vidage implicite. En utilisant l’impression de style C, je pense que la méthode que vous avez suggérée ( fflush() ) est le seul moyen.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X