FreeBSD/nut - отключение сервера при пропадании электропитания

Материал из Lblss.ru
Перейти к: навигация, поиск

Содержание

Постановка задачи

Имеется сервер с FreeBSD (localhost) и хранилище NAS (nas.local). Прикупили UPS Powercom BNT-1200 AP, от которого и запитали эти устройства. Необходимо обеспечить выключение сервера и сетевого хранилища при снижении заряда батареи.

Замечания для FreeBSD 13.2

После обновления ОС до релиза 13.2 весной 2023 года и обновления ПО до последних версий появились проблемы с запуском. Замечено, что если после загрузки сервера выдернуть провод от UPS из гнезда USB и затем воткнуть его обратно, то запуск идет успешно. Беглый анализ показал, что теперь вместо пользователя и группы uucp следует использовать соответственно пользователя и группу nut. Потому при установке/настройке по данной шпаргалке следует делать соответствующие изменения.

Установка и настройка

$ sudo portinstall nut
┌───────────────────────────── net-snmp-5.7.2_2 ───────────────────────────────┐
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ [ ] AX_SOCKONLY    Disable UDP/TCP transports for agentx                 │ │
│ │ [ ] DMALLOC        Enable dmalloc debug memory allocator                 │ │
│ │ [x] DUMMY          Enable dummy values as placeholders                   │ │
│ │ [ ] IPV6           IPv6 protocol support                                 │ │
│ │ [ ] MFD_REWRITES   Build with 64-bit Interface Counters                  │ │
│ │ [ ] MYSQL          MySQL database support                                │ │
│ │ [x] PERL           Perl scripting language support                       │ │
│ │ [x] PERL_EMBEDDED  Build embedded perl                                   │ │
│ │ [ ] PYTHON         Python bindings or support                            │ │
│ │ [ ] TKMIB          Install graphical MIB browser                         │ │
│ │ [ ] UNPRIVILEGED   Allow unprivileged users to execute net-snmp          │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘
 
┌─────────────────────────────── nut-2.6.5_1 ──────────────────────────────────┐
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ [x] BASH    Bash Completion support                                      │ │
│ │ [ ] CGI     Web CGI interface                                            │ │
│ │ [ ] HAL     HAL (Hardware Abstraction Layer) support                     │ │
│ │ [ ] NEON    NEON XML/HTTP support                                        │ │
│ │ [ ] PDU     Powerman PDU support                                         │ │
│ │ [ ] SERIAL  SERIAL support                                               │ │
│ │ [ ] SNMP    SNMP support                                                 │ │
│ │ [x] USB     USB support                                                  │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

Определение устройств

Смотрим шину USB:

$ sudo usbconfig dump_device_desc
...
ugen1.3: <product 0x00a6 POWERCOM Co.,Ltd> at usbus1, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON
...

Куча вывода пропущена, так как в общем то интересует только эта одна строка.

Системный пользователь

$ grep uucp /etc/{passwd,group}
/etc/passwd:uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico
/etc/group:operator:*:5:root,uucp
/etc/group:uucp:*:66:

Правила devfs

По дефолту USB-устройствам в devfs даны владелец/группа root:wheel с привилегиями 600. Так как, драйвер, работающий от имени пользователя uucp не имеет права записи, то и не сможет установить связь с устройством. Это исправляется в трех файлах.

/etc/devfs.conf

# PowerCom UPS
perm    ugen1.3 0660
own     ugen1.3 root:uucp

/etc/devfs.rules

[nutusb=10]
add path 'usb/1.3.0' group uucp mode 0660

/etc/rc.conf

devfs_system_ruleset="nutusb"

Тут следует заметить, что при указании в правиле симлинка вроде ugen* (именно такой вариант встречается в разного рода HowTo) возникла неприятная ситуация. Если кабель USB отключить, а потом включить заново, то правила не отрабатываются автоматически (по крайней мере, на FreeBSD 9.0) до ручного перезапуска devfs. Если же в devfs.rules прописать "оригинальное" устройство, то проблема пропадает. Определяется просто:

$ ls -l /dev/ugen1.3
lrwxr-xr-x  1 root  wheel  9  2 апр 19:30 /dev/ugen1.3 -> usb/1.3.0

И рестарт devfs, для того чтобы эти правила вступили в силу:

$ sudo service devfs restart

Смотрим, что получилось

$ ls -l /dev/usb/1.3.0
crw-rw----  1 root  uucp    0, 104  2 апр 19:30 /dev/usb/1.3.0

Выбор драйвера

Смотрим в списке доступных драйверов.

$ grep -i powercom /usr/local/etc/nut/driver.list
...
"Powercom"      "ups"   "5"     "BNT-xxxAP"     "USB (product id: 0004)"        "usbhid-ups (experimental)"
...

Обнаружилась наша моделька. Имя драйвера usbhid-ups.

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

$ sudo grep -v ^# /usr/local/etc/nut/ups.conf | strings
[bnt1200ap]
    driver = "usbhid-ups"
    port = /dev/uhid0
    desc = "POWERCOM BNT-1200AP"
    ignorelb
    override.battery.charge.low = 50
    override.battery.charge.warning = 60

На последние три строки стоит обратить внимание. По дефолту команда на выключение пойдет при low уровне батареи. Это значение равно 10%. Однако, нас это не устраивает, так как оставшейся энергии батареи вряд ли хватит для того чтобы обеспечить питанием устройства на время завершения работы. Потому значения переопределены в настройке драйвера.

Пользователи

$ sudo grep -v ^# /usr/local/etc/nut/upsd.users | strings
[apc_rs1000]
password  = rs1000_pass
upsmon master

Еще пара штрихов

$ sudo cp /usr/local/etc/nut/upsd.conf.sample /usr/local/etc/nut/upsd.conf
$ sudo chown uucp:uucp /usr/local/etc/nut/*.{conf,users}
$ sudo chmod 640 /usr/local/etc/nut/*.{conf,users}

В конфиге upsd.conf править ничего не нужно (все строки закомментированы). А вот права и владельца файлов нужно сменить.

Запуск драйвера

Добавляем в /etc/rc.conf строку

nut_enable="YES"

Стартуем драйвер

$ sudo service nut start

И внимательно (!) смотрим вывод на наличие варнингов и прочих ошибок.

Монитор

$ sudo cp /usr/local/etc/nut/upsmon.conf.sample /usr/local/etc/nut/upsmon.conf

Как и выше, меняем владельца и права файла.

Вносим необходимые изменения:

  • Указываем что будем мониторить:
MONITOR bnt1200ap@localhost 1 powercom PWComPass master
  • Какую команду следует выполнить при снижении уровня батарей до low (здесь будет наш скрипт):
SHUTDOWNCMD "/root/sbin/powerdown.sh"

Скрипт выключения

$ cat /root/sbin/powerdown.sh
#!/bin/sh
/usr/bin/ssh root@nas.local "poweroff &"
/sbin/shutdown -p now

Первая команда выключает удаленный сервер, вторая - локальный.

Ссылки

Персональные инструменты