Pull to refresh

ZABBIX+Apcupsd: собираем статистику работы ИБП

Суть


Zabbix-сервер через механизм внешних проверок при помощи APCupsd и нехитрого скрипта собирает информацию о работе бесперебойника с ряда машин (как c Windows, так и Linux), обрабатывает и представляет ее нам в удобочитаемом виде.

Предистория


Исторически так сложилось что на ввереном мне обьекте все время было что-то не в порядке с энергоснабжением. С перебоями не справлялись ни система АВР, ни древние упсы из автомобильных аккумуляторов и хэнд-мэйд стабилизатора. И вот настал счастливый день, когда нам привезли новенькие мощные умные APC Smart-UPS. Сразу же захотелось сделать все «как положено»: с системой аварийного завершения работы и мониторинга состояния системы. Однако при первой же попытке установить комплектный софт от APC выяснилось, что он ни в какую не хочет работать с Windows Hyper-V серверами, а нехитрый установщик предложил мне перейти на сайт и приобрести (!) необходимую версию ПО. Такой поворот был недопустим. Вот тогда и родилась идея (не без помощи Google) о сторонних утилитах. Во что это вылилось — читайте дальше.

APCUPSD


APCUPSD — это кросcплатформенная опенсорсная утилита, а точнее комплекс утилит для работы с ИБП APC и другими, созданная в лучших традициях POSIX. Сама по себе она умеет получать данные упса, выключать компьютер при потере питания, и, что самое важное для нас — давать знать о состоянии ИБП всем желающим по сети. Это, в свою очередь, дает возможность работать нескольким машинам от одного ИБП, ровно как и получать необходимую статистическую информацию.
С сайта можно скачать версию как для *NIX, так и для Win и Mac. Компилятся и ставятся все они без проблем. Все настройки находятся в одном конфигурационном файле, отлично раскоменченом и не вызывающем вопросов. Нас в нем интересуют следующие строки:

# Настраиваем соединение с ИБП (зависит от вашей модели
)
UPSCABLE usb
UPSTYPE usb
DEVICE
# Частота опроса ИБП. Мы же не хотим узнать что упс отключился только # когда он уже отключился?
POLLTIME 25
# Разрешаем отправлять состояние упса по сети
NETSERVER on
# Указываем интерфейс и порт для отправки
NISIP 0.0.0.0
NISPORT 3551


Поставить и настроить демон потребуется на всех машинах, которые мы хотим мониторить. В его состав входят несколько вспомогательных утилит. На самом Zabbix-сервере достаточно будет бинарника apcaccess, входящего в сабжевый пакет.

Скрипт


Скрипт использует для своей работы утилиты linux sed, stat, date и бинарник apcaccess из пакета apcupsd. Последний применяется для получения информации через сеть от демона apcupsd. Чтобы узнать на что способен ваш упс и что впоследствии придется распарсить введем следующее:
apcaccess status host_ip

где host_ip — адрес машины с работающим упсом и apcupsd на ней.
В моем случае вывод был впечатляющим, но меня заинтересовали только несколько ключевых строк:

APC : 001,053,1301
DATE : 2010-11-25 21:18:36 +0200
UPSNAME : MysuperUPS100500
...
CABLE : APC Cable 940-0024C
MODEL : Smart-UPS RT 2000 XL
STATUS : ONLINE
LINEV : 227.5 Volts
LOADPCT : 12.0 Percent Load Capacit
BCHARGE : 100.0 Percent
TIMELEFT : 77.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME : 0 Seconds
MAXLINEV : 228.9 Volts
MINLINEV : 226.0 Volts
OUTPUTV : 230.4 Volts
....


Что ж, текст у нас есть, теперь дело за малым — распарсить его и передать интересующие нас вещи в Zabbix. Для этого создадим в директории, определенной в Zabbix_server.conf в параметре ExternalScripts, файл apcupsdsh следующего содержания:



#!/bin/bash
# Сохраняем вывод apcaccess в промежуточный файл не чаще чем раз в
# delay секунд. Это резко уменьшает объем трафика и количество
# обращений к не шибко быстрой apcaccess, сделано в целях оптимизации.
delay=25
M=$(stat --format=%Y /etc/zabbix/sh/tmp.$1)
D=$(date +%s)
let d=$D-$delay
if [ $d -gt $M ];
then
# В $1 заббикс передает адрес хоста
apcaccess status $1 > /etc/zabbix/sh/tmp.$1 ;
fi
# В $3 - параметр ключа, который нужно распарсить
case "$3" in
# Здесь берем временный файл и парсим по необходимому нам параметру при
# помощи регекспа sed. Я
# реализовал на мой взгляд самое необходимое.
# Заряд батареи
bcharge) sed -n 's/BCHARGE.*[:].\([0-9]*\).*$/\1/p' /var/zabbix/tmp.$1 ;;
# Состояние электросети
status) s=$(sed -n 's/STATUS.*[:].\([A-Z]*\).*$/\1/p' /var/zabbix/tmp.$1) ;;
# Так как статус - текстовый параметр, а нам проще работать с числом, преобразуем его! Если все хорошо и упс ONLINE - выдаем 1
if [ $s == "ONLINE" ];
then
echo 1 ;
else
# Если что-то не так - ноль
echo 0;
fi
;;
# Нагрузка
loadpct) sed -n 's/^LOADPCT.*[:][ ]*\([0-9]*\.[0-9]*\).*$/\1/p' /var/zabbix/tmp.$1 ;;
# Напряжение питания
linev) sed -n 's/^LINEV.*[:][ ]*\([0-9]*\.[0-9]*\).*$/\1/p' /var/zabbix/tmp.$1 ;;
# Время до отключения (при пропадании питания)
timeleft) sed -n 's/^TIMELEFT.*[:][ ]*\([0-9]*\).*$/\1/p' /var/zabbix/tmp.$1 ;;
# Если нужно - можно продолжить
esac
exit 0

Теперь присвоим необходимые права и владельца для скрипта и временных файлов (временные файлы лучше создать сразу для каждого из хостов, чтобы потом не тратить процессорное время на проверку существования файлов):
touch /etc/zabbix/sh/tmp.host_ip
chown zabbix:zabbix /etc/zabbix/sh/tmp.host_ip
chmod +x /usr/local/etc/zabbix/apcupsdsh

ZABBIX-сервер


Не буду останавливаться на установке Zabbix, благо мануалов в сети предостаточно. Нам потребуется лишь подправить параметр ExternalScripts в конфигурационном файле zabbix_server.conf:
ExternalScripts=/usr/local/etc/zabbix

Именно в эту папку необходимо поместить созданный нами скрипт.
Теперь идем в веб-админку и создаем новый шаблон. (Настройка -> Шаблоны->Создать шаблон)
Сама структура шаблона: элементы данных и триггеры — зависит от ваших потребностей, возможностей вашего ИБП, и вашей фантазии.
У меня это выглядит примерно так:



Вся магия происходит в элементах данных. Чтобы zabbix начал взаимодействовать со скриптом необходимо создать элемент данных типа «Внешняя проверка». Поле ключ должно иметь следующий вид:

apcupsdsh[{HOST.CONN} status]

где:
apcupsdsh — имя внешней команды (то есть имя скрипта);
{HOST.CONN} — макрос Zabbix, который преобразуется в адрес хоста в при выполнении проверки;
status — один из параметров, которые может принимать скрипт.

К слову можно сказать что параметров может быть больше, но нас сейчас это интересует.
Дальше выбираем тип данных, который должен возвращать скрипт. В случае status это целое (0 или 1). Остальное можно заполнить по вкусу.
Также к шаблону можно добавить триггеры и графики. Я, к примеру, сделал триггер на потерю питания, и график напряжений, а затем вывел его на Dashboard. Принцип создания триггеров базируется на элементарной логике — если Выражение становится true, то выстреливает событие назначенной важности с назначенным сообением. Выражение можно написать вручную:

{APCUPSD:apcupsdshHOST.CONN} status].last(0)}=0

Или воспользоваться мастером, что гораздо проще:

Собственно все, шаблон создан, теперь осталось только добавить к нему узлы и система начнет работу. Теперь в любое время можно посмотреть как себя вела сеть в тот или иной период, а в случае настроенных оповещений еще и вовремя узнать о неполадках.

Резюме


Данный метод несет в себе больше образовательный смысл, нежели практический. Хотя в некоторых случаях он и может стать реальным решением проблемы. Естественно ставить такой комплекс как Zabbix только для мониторинга ИБП было бы излишеством. Кроме того под вопросом производительность данного решения — в моем случае сервер легко с этим справился, однако насколько это масштабируемо мне неизвестно. В мануалах Zabbix не рекомендуют злоупотреблять внешними проверками. В принципе это возможно было бы положить на плечи zabbix-агентов, однако тут налицо увеличение количества работы над скриптами. В любом случае целью было познакомиться с возможностями zabbix, а также попрактиковаться в написании скриптов, а уж никак не придумать универсальное средство.

Источники

1.APCUPSD
2.Zabbix server
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.