Puis-je désactiver la mise en mémoire tampon pour tr

10

trsemble mettre en mémoire tampon son entrée afin que cette commande LongRunningCommand|tr \\n ,ne commence à produire une sortie qu'après l'accumulation de quelques kilo-octets d'entrée de LongRunningCommand.

Existe-t-il un moyen de forcer l' trarrêt de cette mise en mémoire tampon ou toute autre commande pouvant remplacer les sauts de ligne par un autre caractère sans mise en mémoire tampon?


PS J'ai déjà essayé les deux premières suggestions de Turn off buffering in pipe sans succès.

ndemou
la source
1
avez-vous appliqué stdbufà LongRunningCommand ou à tr, ou aux deux, différemment?
meuh
Pour les deux comme ça:stdbuf -o0 fping -aAq -r2 -g 10.30.0.1 10.30.0.255 2>/dev/null | stdbuf -i0 tr \\n ,
ndemou
fping -qdit "Ne montrez pas les résultats par sonde, mais seulement le résumé final", alors peut-être qu'il n'y a qu'une longue écriture à la fin?
meuh
Non, la commande fping fonctionne bien en elle-même. Merci beaucoup pour les suggestions
ndemou
2
Je pense que le problème de mise en mémoire tampon est en fait dans la sortie de tr. Essayez|stdbuf -i0 -o0 tr ...
meuh

Réponses:

12

Les commandes ne tamponnent généralement pas leur entrée. Ils feraient un read()pour un gros morceau, mais lors de la lecture à partir d'un canal, s'il n'y a pas autant d'octets dans le canal, l' read()appel système retournera avec autant de caractères qu'il y a et l'application fonctionnera généralement avec cela si elle le peut .

Une exception notable est celle mawkqui continuera read()jusqu'à ce que le tampon d'entrée soit plein.

Les applications tamponnent cependant leur sortie (stdout). Le comportement habituel est que si la sortie va vers un tty, alors la mise en mémoire tampon sera ligne par ligne (c'est-à-dire qu'elle ne commencera pas à écrire sur stdout jusqu'à ce qu'elle ait une ligne complète à sortir, ou un bloc plein pour très longue ligne), tandis que pour tous les autres types de fichiers, la mise en mémoire tampon se fait par blocs (c'est-à-dire qu'elle ne commencera à écrire qu'après avoir un bloc plein à écrire (quelque chose comme 4KiB / 8KiB ... dépend du logiciel et du système) )).

Donc, dans votre cas, LongRunningCommandtamponne probablement sa sortie par blocs (puisque sa sortie est un tube et non un tty), et trtamponne probablement sa sortie par ligne car sa sortie est probablement le terminal.

Mais, puisque vous supprimez chaque caractère de nouvelle ligne de sa sortie, il ne sortira jamais de ligne, donc la mise en mémoire tampon sera par bloc.

Ici, vous souhaitez désactiver la mise en mémoire tampon pour les deux LongRunningCommandet tr. Sur les systèmes GNU ou FreeBSD:

stdbuf -o0 LongRunningCommand | stdbuf -o0 tr '\n' ,

Notez que si vous souhaitez joindre les lignes avec une virgule, une meilleure approche consiste à utiliser paste -sd , -. De cette façon, la sortie sera terminée par un caractère de nouvelle ligne (vous devrez probablement toujours désactiver la mise en mémoire tampon).

Stéphane Chazelas
la source
@mikeserv. Oui, et celui qui utilise la mise en mémoire tampon stdio et n'appelle pas setvbuf / setbuffer ... par lui-même et n'est pas un shell intégré. Mais généralement sur les systèmes GNU et FreeBSD, toutes ces conditions sont remplies.
Stéphane Chazelas
Oh. J'ai seulement appris cela moi-même il y a quelques jours quand j'ai été déçu de ne pas pouvoir affecter les flux d'E / S pour mon compilé statiquement sed. désolé si c'était ennuyeux - mais je ne savais pas que c'était des connaissances générales. je suppose qu'il utilise LD_PRELOAD.
mikeserv
Merci pour l'explication approfondie de ce qui se passe Stéphane. Très apprécié
ndemou
5

Pour remplacer les sauts de ligne par ",", vous pouvez exécuter

awk '{ printf "%s,", $0 }'

GNU awk ( gawk) et Solaris nawks'exécuteront avec la mise en mémoire tampon de ligne sur stdin et sans mise en mémoire tampon stdout lorsque la sortie est vers un terminal. Si votre awk l'est mawk, ce qui se produit sur Ubuntu, vous pouvez lui donner la -W interactivepossibilité d'obtenir ce même comportement de mise en mémoire tampon.

Mark Plotnick
la source