Habituellement, stdout
est mis en ligne. En d'autres termes, tant que votre argument printf
se termine par une nouvelle ligne, vous pouvez vous attendre à ce qu'elle soit imprimée instantanément. Cela ne semble pas tenir quand on utilise un tube pour rediriger vers tee
.
J'ai un programme C++, a
, qui génère des chaînes, toujours \n
- terminé, à stdout
.
Lorsqu'il est exécuté par lui-même (./a
), Tout s'imprime correctement et au bon moment, comme prévu. Cependant, si je le redirige vers tee
(./a | tee output.txt
), Il n’affiche rien jusqu’à sa fermeture, ce qui annule le but d’utiliser tee
.
Je sais que je pourrais résoudre ce problème en ajoutant un fflush(stdout)
après chaque opération d'impression dans le programme C++. Mais existe-t-il un moyen plus propre et plus propre? Y a-t-il une commande que je peux exécuter, par exemple, qui forcerait stdout
à être tamponné, même en utilisant un tube?
Essayez unbuffer
qui fait partie du package expect
. Vous l'avez peut-être déjà sur votre système.
Dans votre cas, vous l'utiliseriez comme ceci:
./a | unbuffer -p tee output.txt
(-p
est pour le mode pipeline où le tampon de lecture lit à partir de stdin et le passe à la commande dans le reste des arguments)
vous pouvez essayer stdbuf
$ stdbuf -o 0 ./a | tee output.txt
(grande) partie de la page de manuel:
-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’exécutez pas stdbuf
sur tee
, mais sur a
; elle ne devrait donc pas vous affecter, sauf si vous définissez la mise en mémoire tampon des flux de a
dans la source de a
.
De plus, stdbuf
est pas POSIX, mais fait partie de GNU-coreutils.
Vous pouvez également essayer d'exécuter votre commande dans un pseudo-terminal à l'aide de la commande script
(qui devrait appliquer la sortie en tampon de ligne au canal)!
script -q /dev/null ./a | tee output.txt # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt # Linux
Sachez que la commande script
ne renvoie pas le statut de sortie de la commande encapsulée.
Vous pouvez utiliser setlinebuf à partir de stdio.h.
setlinebuf(stdout);
Cela devrait changer la mise en mémoire tampon en "ligne mise en mémoire tampon".
Si vous avez besoin de plus de flexibilité, vous pouvez utiliser setvbuf.
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.