Por que não posso redirecionar a saída do awk?

0

Eu escrevi este forro para mostrar MB lido / escrito a cada 5 segundos.

#!/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}}'

Quando executado na linha de comando, funciona perfeitamente

./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

No entanto, quando tento colocar a saída em um arquivo, não obtenho nada

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

O que dá?

    
por nullUser 07.11.2015 / 06:18

2 respostas

1

Este é um problema de buffer. O Awk se comporta de maneira diferente dependendo de ser interativo ou não. \n libera o buffer de saída apenas no último caso, caso contrário, como ocorreu, o armazenamento em buffer acontece até que o buffer de saída esteja cheio ou seja esvaziado explicitamente com o comando fflush.

Eventualmente, haverá algo no arquivo de saída se você esperar por tempo suficiente.

Caso contrário, a saída deve ser liberada se você matar iostat , não o script em si.

Como alternativa, veja uma solução simples:

script -c iosum.sh out.txt

Observe que a desativação do buffer (com script ou fflush explícito) está afetando o desempenho, então matar o processo iostat ( pkill -f "iostat -dmz 5" ) ou defini-lo para finalizar após um determinado período de tempo é uma abordagem melhor se você não precisa monitorar o conteúdo do arquivo, por exemplo com um período de captura de dois minutos:

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}}'
    
por 07.11.2015 / 07:03
0

O Awk armazena em buffer toda a saída e apenas grava quando termina a leitura da entrada ou quando o buffer está cheio. Use fflush(stdout) (veja a página do awk man) no seu script awk para certificar-se de que a saída seja corretamente liberada para o disco após cada linha impressa. Assim:

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
    
por 07.11.2015 / 10:31