▫️ Вася решил мониторить температуру произвольных устройств.
▫️ Вася решил использовать для этого sensors
▫️ Вася добавил в конфигурацию агента Zabbix примерно следующие строки:
UserParameter=lm.nvme0Temperature,sensors | tail -n 3 | head -n 1 | awk -F'[:+°]' '{avg+=$3}END{print avg/NR}'
UserParameter=lm.nvme1Temperature,sensors | tail -n 8 | head -n 1 | awk -F'[:+°]' '{avg+=$3}END{print avg/NR}'👉 Некоторое время все было хорошо, потом метрики стали показывать погоду на Марсе.
❓Что не так сделал Вася?
Итак, давайте разберем творчество нашего Васи и поймем в чем он был не прав. Для этого сначала нам нужно понять, что делает его заклинание.
▫️ Начало понятно, он вызывает команду sensors и потом колдует над ее выводом, передавая его по конвейеру.
▫️ Обработка начинается с команды tail, которая берет указанное количество строк от конца вывода. В нашем случае это три или восемь.
▫️ Этот результат передаем команде head, которая берет оттуда первую переданную строку. Таким образом у нас остается только третья или восьмая строка от конца.
▫️ Затем это все передается команде awk, где и происходит основная магия.
🔹
-F'[:+°]' – делим строку по указанным разделителям, искомое нами значение является третьим полем, так как располагается между плюсом и градусом.🔹
{avg+=$3} – суммируем третье поле от всех строк в файле, эта конструкция перекочевала сюда из вышестоящей директивы для процессора, где в выводе не было общей температуры, но была температура по ядрам. В итоге мы отбирали количество строк по числу ядер и выводили среднюю.🔹
END{print avg/NR} – выводит среднее значение разделенное на количество строк в стандартны поток ввода-вывода.👆 В целом – магия грамотная и особых вопросов к ней нет. Но! Ошибочен сам принцип парсинга вывода команды sensors. Дело в том, что он зависит от количества сенсоров и выводимой ими информации.
Вам достаточно поменять что угодно в аппаратной конфигурации, чтобы изменить набор сенсоров и порядок, и количество строк сразу же поплывут. И на месте третьей и восьмой строки может оказаться все что угодно.
Поэтому не следует парсить любой вывод или файл опираясь только лишь на номера строк, это абсолютно ненадежно.
Как быть? Используйте grep. Находим вывод именно нашего сенсора и начинаем плясать он его имени. Допустим у нас есть:
nvme-pci-0100
Adapter: PCI adapter
Composite: +37.9°C (low = -0.1°C, high = +114.8°C)
(crit = +119.8°C)
Нас интересует третья строка, в которое находится искомая температура, поэтому пишем:
sensors | grep nvme-pci-0100 -A 2
Которая выведет нам строку с вхождением и еще две после. Затем откусим нижнюю строку через tail:
sensors | grep nvme-pci-0100 -A 2 | tail -n 1
И уже все это скормим awk, вычисление средней можно убрать, так как значение у нас одно:
sensors | grep nvme-pci-0100 -A 2 | tail -n1 | awk -F'[:+°]' '{print $3}'Теперь у нас при любых изменениях количества и порядка строк будет выводиться правильная информация. Либо перестанет выводиться вообще, если такой сенсор пропадет. Но погоды на Марсе уже не будет.
