===== Настройка Network UPS Tools (NUT) для контролируемого выключения сервера с ОС Debian GNU/Linux, подключенного к двум ИБП APC Smart-UPS с платами управления Инматикс ПСУ Спутник ===== {{:unix-linux:debian:bullseye:pasted:20250507-114445.png }} В этой заметке мы рассмотрим пример настройки свободного программного обеспечения **Network UPS Tools** (**NUT**) для контролируемого выключения сервера на базе ОС **Debian GNU**/**Linux**. В рассматриваемом примере NUT будет использоваться в связке с двумя ИБП **APC Smart-UPS SURT6000XLI**, в которые установлены ранее рассмотренные платы **Инматикс ПСУ Спутник А21**. То есть в нашем случае к двум блокам питания сервера подключены два разных ИБП, а ПО NUT, установленное на сервер, по протоколу **SNMP** будет контролировать состояние обоих ИБП и, в случае проблем с электропитанием на ИБП, инициировать команду штатного выключения хостовой ОС. \\ ==== Установка NUT ==== Все необходимые пакеты можно установить из официальных репозиториев Debian Linux
# apt install nut snmp nut-snmp
Так как конфигурация NUT критична в плане безопасности, мы должны проверить права доступа к конфигурационным файлам. Доступ должен быть разрешён только для **root** (на редактирование) и группе **nut** (на чтение).
# ls -la /etc/nut
total 64 drwxr-xr-x 2 root nut 4096 Apr 25 16:50 . drwxr-xr-x 84 root root 4096 Apr 25 16:50 .. -rw-r----- 1 root nut 1911 Jan 25 2023 nut.conf -rw-r----- 1 root nut 9047 Jan 25 2023 ups.conf -rw-r----- 1 root nut 7363 Jan 25 2023 upsd.conf -rw-r----- 1 root nut 2319 Jan 25 2023 upsd.users -rw-r----- 1 root nut 19786 Jan 25 2023 upsmon.conf -rw-r----- 1 root nut 4201 Jan 25 2023 upssched.conf
Если необходимо (если ситуация с правами отличается от выше указанного примера), можем скорректировать права доступа:
# chown root:nut /etc/nut/*
# chmod 640 /etc/nut/*
Прежде чем перейти к конфигурированию NUT, стоит проверить связь сервера с платами управления обоих ИБП по протоколу SNMP. В нашем примере используется протокол **SNMPv3**:
# snmpwalk -v 3 -u nut-user -l authPriv -a SHA -A 'zN3s8fU!sO1sbPMsF' -x DES -X 'H5iXoLe5x4ZY52w-d' KOM-UP001
# snmpwalk -v 3 -u nut-user -l authPriv -a SHA -A 'fR!sO1sbPMsFzN3s8' -x DES -X 'Le5x4ZYv2w-dH5iXo' KOM-UP002
После каждой команды для ИБП должен отобразиться список параметров и их текущие значения, считанные с плат управления по протоколу SNMP. \\ ==== Конфигурация NUT ==== В рамках данной заметки мы не будем рассматривать архитектуру NUT и возможные варианты настройки конфигурационных файлов NUT, так как ранее эта информация была тезисно изложена в статье [[https://blog.it-kb.ru/2024/04/20/configuring-network-ups-tools-nut-for-shutdown-of-hyper-v-vms-and-virtualization-host-connected-to-two-apc-smart-ups-upss-with-nmc-inmatics-psu-sputnik/|о настройке NUT на Windows Server]]. Далее мы приведём примеры настроенных параметров в конфигурационных файлах NUT без учёта комментариев в этих файлах, обозначив некоторые важные моменты. В первую очередь отредактируем файл **nut.conf**, указав режим работы NUT. Справку по возможным режимам работы можно получить в закомментированных строках nut.conf, либо найти в [[https://networkupstools.org/docs/man/nut.conf.html|man nut.conf]].
# nano /etc/nut/nut.conf
MODE=standalone ---- Настроим конфигурацию драйверов NUT. Для этого отредактируем файл **ups.conf**. Справку по этому конфигурационному файлу можно получить в закомментированных строках файла, либо найти в [[https://networkupstools.org/docs/man/ups.conf.html|man ups.conf]]. Есть разные варианты настройки драйвера и они зависят от типа подключения компьютера с NUT к ИБП и от модели ИБП. Перечень совместимых моделей ИБП и рекомендуемые параметры конфигурации для них можно найти в [[https://networkupstools.org/stable-hcl.html|Hardware compatibility list]]. В нашем случае NUT будет подключаться к ИБП не напрямую через USB, а по сети по протоколу SNMP. Поэтому нам потребуется настроить драйвер **snmp-ups**. В нашем случае к компьютеру с NUT подключены 2 ИБП, доступ к которым мы сконфигурируем по протоколу SNMPv3.
# nano /etc/nut/ups.conf
maxretry = 3 [KOM-UP001] driver = snmp-ups mibs = ietf port = kom-up001.holding.com snmp_version = v3 secLevel = authPriv secName = nut-user authProtocol = SHA authPassword = zN3s8fU!sO1sbPMsF privProtocol = DES privPassword = H5iXoLe5x4ZY52w-d pollfreq = 10 desc = "APC Smart-UPS SURT6000XLI with NMC Sputnik A21" [KOM-UP002] driver = snmp-ups mibs = ietf port = kom-up02.holding.com snmp_version = v3 secLevel = authPriv secName = nut-user authProtocol = SHA authPassword = fR!sO1sbPMsFzN3s8 privProtocol = DES privPassword = Le5x4ZYv2w-dH5iXo pollfreq = 10 desc = "APC Smart-UPS SURT6000XLI with NMC Sputnik A21" ---- Следующим шагом настроим серверную компоненту **upsd** таким образом, чтобы upsd не был доступен по сети и прослушивал только локальный порт 3493, отредактировав файл **upsd.conf**:
# nano /etc/nut/upsd.conf
LISTEN 127.0.0.1 3493 ---- Далее настроим конфигурационный файл **upsd.users** с пользователями, которые будут иметь доступ к серверу **upsd** (не путать с пользователями Linux. Подробнее в [[https://networkupstools.org/docs/man/upsd.users.html|man upsd.users]]). Внесём в файл секцию с описанием пользователя, например, с именем ''upsmon-user'', указав ему произвольный пароль:
# nano /etc/nut/upsd.users
[upsmon-user] password = sImplePZsw0rd upsmon primary ---- Затем настроим конфигурационный файл компоненты мониторинга **upsmon**. Для этого редактируем файл **upsmon.conf** (приведены только добавленные/раскомментированные/отредактированные строки):
# nano /etc/nut/upsmon.conf
MONITOR KOM-UP001@localhost 1 upsmon-user sImplePZsw0rd primary MONITOR KOM-UP002@localhost 1 upsmon-user sImplePZsw0rd primary MINSUPPLIES 1 SHUTDOWNCMD "/sbin/shutdown -h +0" NOTIFYCMD /sbin/upssched POLLFREQ 5 POLLFREQALERT 5 HOSTSYNC 15 DEADTIME 15 POWERDOWNFLAG /etc/nut/killpower NOTIFYMSG ONLINE "UPS %s on line power" NOTIFYMSG ONBATT "UPS %s on battery" NOTIFYMSG LOWBATT "UPS %s battery is low" NOTIFYMSG FSD "UPS %s: forced shutdown in progress" NOTIFYMSG COMMOK "Communications with UPS %s established" NOTIFYMSG COMMBAD "Communications with UPS %s lost" NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding" NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced" NOTIFYMSG NOCOMM "UPS %s is unavailable" NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible" NOTIFYFLAG ONLINE SYSLOG+EXEC NOTIFYFLAG ONBATT SYSLOG+EXEC NOTIFYFLAG LOWBATT SYSLOG+EXEC NOTIFYFLAG FSD SYSLOG NOTIFYFLAG COMMOK SYSLOG NOTIFYFLAG COMMBAD SYSLOG NOTIFYFLAG SHUTDOWN SYSLOG NOTIFYFLAG REPLBATT SYSLOG NOTIFYFLAG NOCOMM SYSLOG NOTIFYFLAG NOPARENT SYSLOG RBWARNTIME 43200 NOCOMMWARNTIME 600 FINALDELAY 5 Первые две строки определяют подключение компоненты мониторинга к драйверам, описанным нами в ups.conf с учётной записью, описанной нами в upsd.users. Третья строка с параметром MINSUPPLIES определяет минимально допустимое количество источников питания в состоянии ONLINE. На сервере с двумя блоками питания, подключенным к двум разным ИБП, логично определить значение этого параметра в 1. На сервере с 4 блоками питания, подключенными к разным источникам питания, это значение может быть, например, 2 или 3. Важным здесь также являются параметры NOTIFYFLAG. Обратите внимание на то, что для большинства разных состояний источников питания у нас определено лишь логирование (SYSLOG). И только для трёх состояний (ONLINE, ONBATT, LOWBATT) мы включаем логирование и запуск команды (SYSLOG+EXEC). Под командой здесь подразумевается исполняемый файл планировщика upssched, ссылка на который описана в параметре NOTIFYCMD. Чтобы лучше понять все описанные параметры, рекомендуется ознакомиться со справкой по этому конфигурационному файлу, которую можно получить в закомментированных строках файла, либо найти в [[https://networkupstools.org/docs/man/upsmon.conf.html|man upsmon.conf]]. ---- Настроим конфигурационный файл **upssched.conf** вспомогательного планировщика **upssched**, который вызывается в NOTIFYCMD конфигурации компоненты upsmon:
# nano /etc/nut/upssched.conf
CMDSCRIPT /usr/bin/upssched-script.sh PIPEFN /run/nut/upssched.pipe LOCKFN /run/nut/upssched.lock AT LOWBATT * EXECUTE ups-on-battery AT ONBATT * START-TIMER ups-on-battery 3600 AT ONLINE * CANCEL-TIMER ups-on-battery Данная конфигурация предполагает то, что после того, как любой из ИБП переходит в состояние работы от батарей (ONBATT) запускается таймер, ожидающий 1 час (3600 секунд). Это время может корректироваться в зависимости от возможностей ваших ИБП по времени автономной работы от батарей при пропадании входного напряжения. Если в течение указанного периода времени входное напряжение на ИБП вернётся и он перейдёт с батарей на питание от сети (возврат в статус ONLINE), то обратный отсчёт времени таймера будет прерван. Если обратный отсчёт времени таймера доработает до конца, то произойдёт вызов скрипта завершения работы (CMDSCRIPT) с передачей ему параметра "ups-on-battery". При этом, в любой из ситуаций, если с любого из ИБП будет получен статус об исчерпании заряда батарей (LOWBATT), то будет выполнен вызов скрипта завершения работы (CMDSCRIPT) с передачей ему параметра "ups-on-battery". ---- Создаем файл скрипта **upssched-script.sh**:
# nano /usr/bin/upssched-script.sh
#!/bin/bash ############################################################################### # NUT UPS Monitoring Script with Advanced Communication Loss Protection # Version: 2.1 # # Features: # - Prevents shutdown on communication loss with all UPS units # - Respects MINSUPPLIES parameter from upsmon.conf # - Differentiates between power loss and communication issues # - Comprehensive logging and status tracking # - Supports calibration mode (CAL) as safe state ############################################################################### ### Configuration Section - Adjust these parameters as needed ### UPSMON_CONF="/etc/nut/upsmon.conf" # Path to NUT main configuration LOG_IDENT="NUT-UPS-Monitor" # Syslog identification tag SAFE_UPS_STATES="OL CAL" # States considered operational (space-separated) COMM_RETRY_INTERVAL=30 # Seconds between communication retries MAX_COMM_FAILURES=3 # Allowed consecutive communication failures ### Initialization Section ### # Read MINSUPPLIES from config with fallback to default value 1 MINSUPPLIES=$(grep -oP '^MINSUPPLIES\s+\K\d+' "$UPSMON_CONF" 2>/dev/null || echo 1) # Get list of all configured UPS devices (filtering out SSL messages) UPS_LIST=$(upsc -l 2>/dev/null | grep -v '^Init SSL') TOTAL_UPS=$(echo "$UPS_LIST" | wc -w) ### Status Tracking Variables ### SAFE_UPS_COUNT=0 # Count of UPS in safe states COMM_FAILURE_COUNT=0 # Count of consecutive communication failures declare -a UPS_STATUSES # Array to store detailed UPS states ############################################################################### # Function: check_ups_status # Description: Checks and logs the status of a specific UPS unit # Arguments: # $1 - UPS identifier ############################################################################### check_ups_status() { local ups_id=$1 local status # Get UPS status with error handling status=$(upsc "$ups_id" 2>/dev/null | grep -oP 'ups.status:\s*\K\w+') # Handle communication failures if [ -z "$status" ]; then status="NOCOMM" ((COMM_FAILURE_COUNT++)) logger -t "$LOG_IDENT" -p warn "Communication failed with UPS $ups_id (Attempt $COMM_FAILURE_COUNT/$MAX_COMM_FAILURES)" else # Reset communication failure counter on successful contact COMM_FAILURE_COUNT=0 fi # Check against safe states for safe_state in $SAFE_UPS_STATES; do if [[ "$status" == "$safe_state" ]]; then ((SAFE_UPS_COUNT++)) logger -t "$LOG_IDENT" "UPS $ups_id operational (Status: $status)" break fi done # Store detailed status for reporting UPS_STATUSES+=("$ups_id:$status") } ############################################################################### # Main Event Handler # Processes ups-on-battery events and makes shutdown decisions ############################################################################### case $1 in ups-on-battery) ### Check all UPS units for ups in $UPS_LIST; do check_ups_status "$ups" done ### Communication Failure Protection ### if [ $COMM_FAILURE_COUNT -ge $MAX_COMM_FAILURES ]; then logger -t "$LOG_IDENT" -p err \ "CRITICAL: Persistent communication failures with $COMM_FAILURE_COUNT UPS units" logger -t "$LOG_IDENT" -p err \ "Possible network/SNMP issue. NOT initiating shutdown." exit 2 fi ### Power State Evaluation ### if [ "$SAFE_UPS_COUNT" -lt "$MINSUPPLIES" ]; then # Genuine power failure condition logger -t "$LOG_IDENT" -p crit \ "POWER FAILURE: Only $SAFE_UPS_COUNT/$TOTAL_UPS UPS operational (Required: $MINSUPPLIES)" logger -t "$LOG_IDENT" -p crit \ "Detailed status: ${UPS_STATUSES[*]}" logger -t "$LOG_IDENT" "Initiating controlled shutdown..." # Create powerdown flag file touch /etc/nut/killpower 2>/dev/null # Execute shutdown command /usr/sbin/upsmon -c fsd else # Adequate power protection available logger -t "$LOG_IDENT" \ "Power stable: $SAFE_UPS_COUNT/$TOTAL_UPS UPS operational (Required: $MINSUPPLIES)" fi ;; *) # Unknown event type handler logger -t "$LOG_IDENT" -p warn "Received unconfigured event: $1" exit 1 ;; esac exit 0 Разрешим исполнение скрипта:
# chmod +x /usr/bin/upssched-script.sh
---- Перезапускаем службы NUT и убеждаемся в том, что службы запустились без ошибок:
# systemctl restart nut-server nut-monitor
# systemctl status nut-server nut-monitor
Убедиться в правильности настройки связи NUT с платами управления ИБП можно введя команды:
# upsc KOM-UP001
# upsc KOM-UP002
Проверку работы скрипта завершения работы можно выполнить в любое время, вызвав его с параметром "ups-on-battery" (при нормальном состоянии ИБП скрипт не должен вызывать выключение ОС, а лишь фиксировать в системном логе информацию о текущем состоянии обоих подключенных ИБП):
# /usr/bin/upssched-script.sh ups-on-battery
Результат работы скрипта можем увидеть в системном журнале:
# journalctl -n 50 | grep NUT-UPS
\\ ---- Дополнительные источники информации: * [[https://blog.it-kb.ru/2024/04/20/configuring-network-ups-tools-nut-for-shutdown-of-hyper-v-vms-and-virtualization-host-connected-to-two-apc-smart-ups-upss-with-nmc-inmatics-psu-sputnik/|Настройка Network UPS Tools (NUT) для контролируемого выключения хоста Hyper-V, подключенного к двум ИБП APC Smart-UPS с платами управления Инматикс ПСУ Спутник]] ---- Проверено на следующих конфигурациях: ^ Версия ОС ^ Версия NUT ^ | Debian GNU/Linux 11 (Bullseye) | 2.7.4-13 | | Debian GNU/Linux 12 (Bookworm) | 2.8.0-7 | ---- {{:user:blogroot.png?50&nolink |}} Автор первичной редакции:\\ [[user:blogroot|Алексей Максимов]] \\ Время публикации: 07.05.2025 12:16 {{tag>APC "Network UPS Tools" Linux Debian NMC NUT Bash Script Shutdown "Smart-UPS" SNMP UPS Инматикс "ПСУ Спутник"}} ~~DISCUSSION~~ ~~NOTOC~~