Вики IT-KB

Пошаговые руководства, шпаргалки, полезные ссылки...

Инструменты пользователя

Инструменты сайта


unix-linux:debian:bullseye:configuring-network-ups-tools-nut-for-shutdown-of-debian-linux-host-connected-to-two-apc-smart-ups-upss-with-nmc-inmatics-psu-sputnik

Настройка Network UPS Tools (NUT) для контролируемого выключения сервера с ОС Debian GNU/Linux, подключенного к двум ИБП APC Smart-UPS с платами управления Инматикс ПСУ Спутник

В этой заметке мы рассмотрим пример настройки свободного программного обеспечения 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, так как ранее эта информация была тезисно изложена в статье о настройке NUT на Windows Server. Далее мы приведём примеры настроенных параметров в конфигурационных файлах NUT без учёта комментариев в этих файлах, обозначив некоторые важные моменты.

В первую очередь отредактируем файл nut.conf, указав режим работы NUT. Справку по возможным режимам работы можно получить в закомментированных строках nut.conf, либо найти в man nut.conf.

# nano /etc/nut/nut.conf
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
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
upsd.conf
LISTEN 127.0.0.1 3493

Далее настроим конфигурационный файл upsd.users с пользователями, которые будут иметь доступ к серверу upsd (не путать с пользователями Linux. Подробнее в man upsd.users). Внесём в файл секцию с описанием пользователя, например, с именем upsmon-user, указав ему произвольный пароль:

# nano /etc/nut/upsd.users
upsd.users
[upsmon-user]
password = sImplePZsw0rd
upsmon primary

Затем настроим конфигурационный файл компоненты мониторинга upsmon. Для этого редактируем файл upsmon.conf (приведены только добавленные/раскомментированные/отредактированные строки):

# nano /etc/nut/upsmon.conf
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
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
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



Дополнительные источники информации:


Проверено на следующих конфигурациях:

Версия ОС Версия NUT
Debian GNU/Linux 11 (Bullseye) 2.7.4-13
Debian GNU/Linux 12 (Bookworm) 2.8.0-7

Автор первичной редакции:
Алексей Максимов
Время публикации: 07.05.2025 12:16

Обсуждение

Ваш комментарий:
 
unix-linux/debian/bullseye/configuring-network-ups-tools-nut-for-shutdown-of-debian-linux-host-connected-to-two-apc-smart-ups-upss-with-nmc-inmatics-psu-sputnik.txt · Последнее изменение: Алексей Максимов

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki