Я пишу сценарий оболочки, чтобы проверить vmstat si
и so
данные в разные промежутки времени
vmstat 1
образец вывода:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 45820 899252 86700 468520 0 0 0 60 127 5821 20 7 34 0
0 0 45820 899252 86704 468504 0 0 0 32 44 104 0 0 100 0
Я хочу использовать awk, sed для извлечения si
и so
в разные переменные для дальнейшего использования. Я новичок в awk, sed и все еще пытаюсь найти свой путь. Вы можете показать мне, как я могу это сделать?
Этот сценарий AWK считывает вторую строку и использует заголовки полей в качестве индексов данных в каждой строке, чтобы вы могли ссылаться на них по имени. Вот однострочный. Я разбиваю его по строкам ниже.
vmstat -n 1 | awk 'NR == 1 {next} NR == 2 {for (i = 1; i <= NF; i++) fields[$i] = i; next} {split($0, data); item = data[fields["si"]]; print item; totals[fields["si"]] += item} NR >= 6 + 2 {exit} END {print "Average", totals[fields["si"]]/(NR - 2)}'
Как показано, он печатает содержимое столбца «si» и среднее значение в конце. Вы можете обрабатывать несколько полей или перебирать все поля.
Вы можете расширить это, чтобы обрабатывать другие поля, сравнивать одну строку с предыдущей или выполнять итоги или другие вычисления. Вы можете остановиться, как я показал, после определенного количества записей.
В -n
возможность vmstat
заставляет заголовок печататься только один раз.
Разбивка:
vmstat -n 1 | awk 'NR == 1 {next} # skip the first line
# for the second line, create an array of field positions indexed by the
# name of the field then do "next" so this line is not processed further
NR == 2 {for (i = 1; i <= NF; i++) fields[$i] = i; next}
{split($0, data); # split the line of values into an array
item = data[fields["si"]]; # pick out an item based on its name
print item;
totals[fields["si"]] += item} # accumulate a total
# exit when the number of desired records (plus the two header lines)
# has been read, you could use a vmstat argument to do this instead
NR >= 10 + 2 {exit}
# calculate and print the average (subtract the two header lines from the record count)
END {print "Average", totals[fields["si"]]/(NR - 2)}'
SWAPIN=$(vmstat | egrep -v 'swap|si' | awk '{ print $7 }')
SWAPOUT=$(vmstat | egrep -v 'swap|si' | awk '{ print $8 }')
или более «стандартным» способом:
$ vmstat | awk '{ for (i=1; i<=NF; i++) if ($i=="si") { getline; print $i }}'
NF
переменная дает вам количество полей в текущей строкеgetline
читает следующую строку вводаЯ чувствовал бы себя упущенным, если бы не предоставил эквиваленты perl oneliner:
SWAPIN=$(vmstat | perl -lane 'next if /^(procs|r)/; print $F[7]')
SWAPOUT=$(vmstat | perl -lane 'next if /^(procs|r)/; print $F[8]')