shikhalev.*

Продолжая тему 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. ↩