Я написал этот вкладыш, чтобы показывать МБ для чтения / записи каждые 5 секунд.

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

При запуске из командной строки работает отлично

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

Однако, когда я пытаюсь поместить вывод в файл, я ничего не получаю

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

Что дает?

2 ответа2

1

Это проблема буферизации. Awk ведет себя по-разному в зависимости от того, интерактивен он или нет. \n очищает выходной буфер только в последнем случае, иначе, как вы уже видели, буферизация происходит до тех пор, пока выходной буфер не заполнится или не будет явно сброшен командой fflush.

В конце концов, в выходном файле будет что-то, если вы будете ждать достаточно долго.

В противном случае вывод должен быть сброшен, если вы убьете iostat , а не сам скрипт.

В качестве альтернативы вот простой обходной путь:

script -c iosum.sh out.txt

Обратите внимание, что отключение буферизации (с помощью script или явного fflush) влияет на производительность, поэтому лучше убить процесс iostat (pkill -f "iostat -dmz 5") или установить его для завершения через определенный промежуток времени, если вы не необходимо контролировать содержимое файла, например, с двухминутным периодом захвата:

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}}'
0

Awk буферизирует весь вывод и записывает его только тогда, когда он заканчивает чтение ввода или когда буфер заполнен. Используйте fflush(stdout) (см. Man-страницу awk) в вашем скрипте awk, чтобы убедиться, что вывод правильно записан на диск после каждой напечатанной строки. Как это:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .