Пошаговые руководства, шпаргалки, полезные ссылки...
БлогФорумАвторы
Полезные Online-сервисы
Перечень Бесплатного ПО
Подписка на RSS-канал
В этой заметке мы рассмотрим пример настройки свободного программного обеспечения Network UPS Tools (NUT) для контролируемого выключения сервера на базе ОС Debian GNU/Linux. В рассматриваемом примере NUT будет использоваться в связке с двумя ИБП APC Smart-UPS SURT6000XLI, в которые установлены ранее рассмотренные платы Инматикс ПСУ Спутник А21. То есть в нашем случае к двум блокам питания сервера подключены два разных ИБП, а ПО NUT, установленное на сервер, по протоколу SNMP будет контролировать состояние обоих ИБП и, в случае проблем с электропитанием на ИБП, инициировать команду штатного выключения хостовой ОС.
Все необходимые пакеты можно установить из официальных репозиториев 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 на Windows Server. Далее мы приведём примеры настроенных параметров в конфигурационных файлах NUT без учёта комментариев в этих файлах, обозначив некоторые важные моменты.
В первую очередь отредактируем файл nut.conf, указав режим работы NUT. Справку по возможным режимам работы можно получить в закомментированных строках nut.conf, либо найти в man nut.conf.
# nano /etc/nut/nut.conf
MODE=standalone
Настроим конфигурацию драйверов NUT. Для этого отредактируем файл ups.conf. Справку по этому конфигурационному файлу можно получить в закомментированных строках файла, либо найти в man ups.conf.
Есть разные варианты настройки драйвера и они зависят от типа подключения компьютера с NUT к ИБП и от модели ИБП. Перечень совместимых моделей ИБП и рекомендуемые параметры конфигурации для них можно найти в 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. Подробнее в man upsd.users). Внесём в файл секцию с описанием пользователя, например, с именем upsmon-user, указав ему произвольный пароль:
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.
Чтобы лучше понять все описанные параметры, рекомендуется ознакомиться со справкой по этому конфигурационному файлу, которую можно получить в закомментированных строках файла, либо найти в 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
Дополнительные источники информации:
Проверено на следующих конфигурациях:
Автор первичной редакции: Алексей Максимов Время публикации: 07.05.2025 12:16