Pourquoi ne puis-je pas rediriger la sortie de awk?

0

J'ai écrit cette ligne pour montrer à MB en lecture / écriture toutes les 5 secondes.

#!/bin/bash
#iosum.sh
iostat -dmz 5 |\
    awk 'BEGIN{rx=wx=0}{if($0 == ""){printf"%.1f %.1f\n",rx,wx}else if($0~/^Device:/){rx=wx=0}else{rx+=$3;wx+=$4}}'

Lorsqu'il est exécuté à partir de la ligne de commande, il fonctionne parfaitement

./iosum.sh
# wait
1.1 0.0
0.0 0.1
0.0 0.0
3.0 3.0
0.0 0.0
# ctrl-c

Cependant, lorsque j'essaie de mettre la sortie dans un fichier, je ne reçois rien

./iosum.sh > out.txt
# wait
# ctrl-c
cat out.txt
# nothing!

Ce qui donne?

nullUser
la source

Réponses:

1

C'est un problème de mise en mémoire tampon. Awk se comporte différemment selon qu'il soit interactif ou non. \npurge le tampon de sortie dans ce dernier cas uniquement, sinon, comme vous l'avez vu précédemment, la mise en mémoire tampon se produit jusqu'à ce que le tampon de sortie soit plein ou explicitement vidé avec la commande fflush.

Finalement, il y aura quelque chose dans le fichier de sortie si vous attendez assez longtemps.

Sinon, le résultat devrait être vidé si vous tuez iostat, pas le script lui-même.

Alternativement, voici une solution de contournement simple:

script -c iosum.sh out.txt

Notez que la désactivation de la mise en mémoire tampon (avec scriptou explicitement fflush) affecte les performances. Il est donc préférable d’ éliminer le iostatprocessus ( pkill -f "iostat -dmz 5") ou de le mettre fin au bout d’une période donnée si vous n’avez pas besoin de surveiller le contenu du fichier, par exemple deux. minute de capture:

iostat -dmz 5 120 |\
    awk 'BEGIN{rx=wx=0}{if($0 == ""){printf"%.1f %.1f\n",rx,wx}else if($0~/^Device:/){rx=wx=0}else{rx+=$3;wx+=$4}}'
jlliagre
la source
En effet, c'était un problème de mise en mémoire tampon. Je ne sais pas pourquoi c'était un problème de mise en mémoire tampon ... mais l'ajout fflush(stdout)après l'impression a corrigé le problème.
nullUser
En fait, je suis en train de rediriger la sortie de ce script vers une barre d'état. La sortie doit donc être instantanée. Il ne produit qu'une ligne de sortie toutes les 5 secondes. Cela affecte-t-il vraiment les performances?
nullUser
Non, tu as raison. Un taux de cinq secondes rend mon point de performance discutable. Cela ne ferait que mal avec un débit élevé.
Jlliagre
0

Awk met en tampon toutes les sorties et ne l'écrit qu'à la fin de la lecture des entrées ou lorsque la mémoire tampon est pleine. Utilisez fflush(stdout)(voir la page de manuel awk) dans votre script awk pour vous assurer que la sortie est correctement vidée sur le disque après chaque ligne imprimée. Comme ça:

iostat -dmz 5 |\
       awk 'BEGIN{rx=wx=0}{if($0 == ""){printf"%.1f %.1f\n",rx,wx;fflush(stdout)}else if($0~/^Device:/){rx=wx=0}else{rx+=$3;wx+=$4}}' > x
Vojtech
la source