voila un petit comportement que je n'arrive pas à comprendre.
(echo ceci est une phrase; sleep 2 ; echo a l endroit) | rev
Cette ligne m'affiche "esarhp enu tse icec" puis attend deux secondes avant d'afficher "tiordne l a". Donc je me dit chouette rev est malin il n'attend pas d'avoir toute l'entrée pour générer la sortie (ce que je supposais).
Mais lorsque je test
(echo ceci est une phrase; sleep 2 ; echo a l endroit) | rev | rev
et bah ça attend deux secondes avant de m'afficher toute la sortie d'un coup.
J'ai fait divers tests mais je n'arrive pas à expliquer cela. Si quelqu'un a une idée du pourquoi.
# shell pipe est consorts
Posté par NeoX . Évalué à 2.
mais le 2e attend que la chaine soit envoyée par le premier rev avant de la traiter
chez moi il suffit de ne pas mettre les () pour que cela fonctionne comme tu le souhaite
le () ouvrant un sous shell.
echo ceci est une phrase; sleep 2 ; echo a l endroit | rev | rev
[^] # Re: shell pipe est consorts
Posté par Grégory Landais (site web personnel) . Évalué à 2.
[^] # Re: shell pipe est consorts
Posté par NeoX . Évalué à 2.
Ca vient peut-etre simplement des pipes, car tu as le meme comportement si tu chaines 2 greps, 1 grep et un rev, un rev et un grep...
le deuxieme pipe ne pouvant probablement pas lire la sortie standard tant que la premier ne l'a pas liberé
# Buffer flush ...
Posté par Arnaud Taffanel . Évalué à 5.
Par contre, pour les deux rev, le buffer n'est vidé que quand le premier rev quitte, donc après les 2 secondes.
Ce qui est étrange c'est que quand stdout est le terminal, un retour à la ligne est sufisant pour vider le buffer de sortie. Apparemment ce n'est pas le cas pour un pipe.
# C'est rev
Posté par Benoît Monin . Évalué à 8.
(echo ceci est une phrase; sleep 2 ; echo a l endroit) | strace rev
Cela donne quelque chose comme ça, pour la sequence de lectures et d'écritures sur l'entrée/sortie standard :
read(0, "ceci est une phrase\n", 4096) = 20
write(1, "esarhp enu tse icec\n", 20) = 20
read(0, "a l endroit\n", 4096) = 12
write(1, "tiordne l a\n", 12) = 12
Avec la redirection, ça donne ça:
(echo ceci est une phrase; sleep 2 ; echo a l endroit) | strace rev | rev
read(0, "ceci est une phrase\n", 4096) = 20
read(0, "a l endroit\n", 4096) = 12
read(0, "", 4096) = 0
write(1, "esarhp enu tse icec\ntiordne l a\n", 32) = 32
L'écriture n'a lieu que lorsque le programme source se ferme.
Tout cela dans le but d'avoir un affichage ligne à ligne lorsque affiché sur ton terminal et une meilleure performance (lecture et écriture par paquet de 4Ko) sinon.
[^] # Re: C'est rev
Posté par IsNotGood . Évalué à 5.
Et en fait ce n'est pas un problème.
La libc ne bufferise pas lorsque c'est un terminal, autrement elle bufferise (le programme doit alors faire des flush() explicites si le comportenant par défaut de la libc ne convient pas).
La commande strace n'indique que les appels noyaux (il peut y avoir plusieurs appels à write() de la libc avant un write() du noyau).
Pour voir les appels de rev à la libc, il faut utiliser ltrace.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.