shikhalev.org

Продолжая тему Conky и мониторинга вообще, разберемся с выводом данных по двум бесперебойникам, подключенным к одному компьютеру. В моем случае они оба фирмы APC, что упрощает задачу, но не до конца.

Закавыка тут именно в том, что их два. Соответственно нужно:

  1. Настроить сервисы apcupsd.

  2. Побороть страсть устройств в Linux к переименованию после каждой1 перезагрузки.

  3. Заставить Conky отображать информацию по обоим.

Вообще, по идее, п. 2 должен идти до п. 1, но… Впрочем, по порядку.

Настройка сервисов

Я как гентушник и ретроград использую OpenRC и понятия не имею, как это все делается при использовании systemd. Впрочем, это должно легко гуглиться.

Во-первых, нужно создать собственно сервисы.

# cd /etc/init.d
# ln -s apcupsd apcupsd.es550g
# ln -s apcupsd apcupsd.xs1400u

Во-вторых, конфиги для них.

# cd /etc/apcupsd
# cp apcupsd.conf es550g.conf
# cp apcupsd.conf xs1400u.conf

В конфигах следует прописать разные входы и выходы. Входы, в моем случае, порты USB, точнее HID-устройства, а выходы — номера портов, с которыми в дальнейшем будем взаимодействовать.

С портами просто — в одном из конфигов меняем значение в строке с переменной NISPORT, например, на 3553. А вот соответствующие HID-устройства еще предстоит определить. Для этого я использовал команду upower -d, в выхлопе которого мы можем видеть номера устройств hiddevN, которые можно прописать в конфиги в переменную DEVICE в виде DEVICE /dev/usb/hiddev0, например. Это будет работать, но номер hiddev может смениться. Поэтому переходим к следующему пункту.

Постоянные симлинки на HID-устройства

В каталоге /etc/udev/rules.d создаем файл правил (например, 80-ups-hiddev.rules):

KERNEL=="hiddev*", ATTRS{serial}=="5B1807T46538", SYMLINK="usb_es550g"
KERNEL=="hiddev*", ATTRS{serial}=="4B1813P15017", SYMLINK="usb_xs1400u"

Где конкретные значения serial взяты все из того же выхлопа команды upower -d, а имена символических ссылок произвольны.

Теперь можно вписать в конфиги в каталоге /etc/apcupsd в переменные DEVICE уже пути через эти ссылки: /dev/usb_es550g и /dev/usb_xs1400u (в моем случае) соответственно.

Перезагружаемся.

Настройка Conky

С одной стороны, в Conky есть специальные выражения для получения данных от сервиса apcupsd, причем есть даже и специальный вызов ${apcupsd host} для выбора хоста и порта… Но, с другой стороны, работает этот вызов один раз, т.е. мы можем выводить данные по любому UPS, но только по одному. Что меня не устроило.

В итоге я опять же решил это дело скриптом. Модуль для этого, как обычно, помещен на GitHub, модуль apcups.

Как это работает

Используется вызов внешней утилиты — apcaccess, выдача которой парсится и помещается в таблицу в памяти, чтобы не дергать внешний вызов на каждое свойство.

Как использовать

Все работает по сути через одну функцию:

function conky_apcups_get(hostport, property, update)

Где первый параметр имеет вид типа localhost:3551, второй означает конкретное свойство (в нижнем регистре), например, bcharge2, а третий выставляется в true в тех случаях, когда нужно обновить данные (по задумке так нужно делать при получении первого свойства для устройства, тогда как для остальных свойств этот параметр выставляем в false или просто опускаем). Ну, то есть такой код:

${lua apcups localhost:3551 model true}
${lua apcups localhost:3551 bcharge}%

Выдаст модель бесперебойника в первой строчке и текущий уровень заряда во второй. При этом вызов apcaccess будет только один за цикл обновления.

Само собой, можно (и лично я так делаю) вызывать функцию в собственном коде на Lua в различных вспомогательных функциях типа xs1400u_model().

Есть, правда, еще мысль — сделать пропуск обновления, т.е. делать его, например, один раз на десять вызовов с update = true: все таки вызов внешней утилиты — операция тяжелая. Подумаю еще.

  1. Про каждую перезагрузку я, конечно, преувеличиваю, но поскольку переименование происходит непредсказуемо, легче не становится. 

  2. Список возможных свойств проще всего получить, вызвав вручную apcaccess из командной строки. Вообще, этот набор зависит от конкретной модели UPS.