最近家里断电了一次,我的群晖因为连接了 UPS 而优雅关机了,但 Linux 服务器由于没有连接 UPS,直接强制断电。这很容易导致数据丢失,严重的硬盘损坏!于是一直没配置的 NUT 今天终于安排上了。 这篇文章就分享一下如何通过 NUT 来实现一台 UPS 同时保护多台设备。
设备情况
群晖 NAS:运行 DSM 7.2
Linux 服务器:运行 AlmaLinux 8.1
施耐德 APC UPS:直接连接到群晖上
NUT 是什么?
要实现这个功能,我们需要用到 NUT (Network UPS Tools)。NUT 是一套监控和管理 UPS 设备的开源工具,它允许多台计算机通过网络共享一个 UPS 的状态信息。
其中关键的组成部份如下:
组件 | 功能说明 |
---|---|
nut-driver | 与物理 UPS 通讯 |
upsd | 暴露 UPS 状态给网络, upsmon 可以从这个获取状态 |
upsmon | 主控模式(primary)可控制关机,从控模式(secondary)只监听 |
upssched | 用于延迟关机或超时判断 |
scripts | 处理状态变化,如发送通知等 |
工作原理如下:
flowchart TD subgraph Device UPS["🔌 UPS (Physical Device)"] end subgraph Server driver["⚙️ nut-driver (upsdrvctl)"] upsd["🧠 upsd (NUT Daemon)"] upsmon_master["📡 upsmon (Primary)"] upssched["⏱️ upssched (Event Scheduler)"] notify_master["🔔 notify.sh (on Server)"] end subgraph Client upsmon_slave["🛰️ upsmon (Secondary)"] notify_slave["🔔 notify.sh (on Client)"] end UPS --> driver driver --> upsd upsd --> upsmon_master upsmon_master --> upssched upssched --> notify_master upsmon_master --> notify_master upsd -->|network| upsmon_slave upsmon_slave --> notify_slave
在这个设置中,群晖 NAS 将作为主服务器(primary),而 Linux 服务器将作为客户端(secondary)。
当市电断开后,Linux 服务器就能从群晖 NAS 上的 upsd 获取到断电的信息,开始倒计时关机,同时通过脚本通知(这里我配置的是企业微信的通知)。
配置群晖 NAS 的 UPS 网络服务器
- 登录群晖 DSM 管理界面
- 打开「控制面板」>「硬件和电源」>「不断电系统」
- 确保已经勾选「启用 UPS 支持」
- 在「UPS 类型」选项中选择「USB」(取决于你的 UPS 连接方式)
- 设置自定义时间或直到电量不足(如果你的UPS电池不靠谱,建议设置个较短的时间)
- 勾选上当系统进入待机模式时关闭 UPS , 不然系统只会在断电后进入待机模式,不会主动关机。
- 向下滚动到「启用 UPS 网络服务器」选项并勾选
- 在「允许的 UPS 设备」下添加你的 Linux 服务器 IP 地址
- 点击「应用」保存设置
这样群晖这边就配置好了。
如果你希望电源恢复后自动重启,可以在「控制面板」>「硬件和电源」>「常规」中,勾选修复电源问题后自动重新启动。
在 Linux 服务器上安装和配置 NUT
- 首先安装 NUT 客户端包:
sudo yum install nut
我当前安装的版本是 2.8.2
(upsd -V 可查看版本)
- 编辑 NUT 的主配置文件:
sudo vi /etc/ups/nut.conf
将模式设置为 netclient
:
MODE=netclient
MODE 可选值如下,可以了解一下。
值 含义说明 standalone 本机使用本地连接的 UPS,所有组件(upsdrv, upsd, upsmon)都在本机运行。用于 单机本地 UPS 管理。 netserver 本机连接本地 UPS,运行 upsd,允许其他网络客户端通过 NUT 协议连接监控。常用于群晖这类做UPS 主控服务器的场景。 netclient 本机不连接 UPS,只通过网络连接远程 UPS 主机(运行 upsd)。本机只运行 upsmon。这是从机最常用的模式。
- 编辑监控配置:
sudo vi /etc/ups/upsmon.conf
添加以下行:
MONITOR ups@192.168.1.7 1 monuser secret secondary
MONITOR 的配置格式如下:
MONITOR
(“primary”|“secondary”)
参数 说明 MONITOR 这是固定关键字,表示这一行是 UPS 监视配置。 system UPS 的名称和主机地址:这里表示远程主机 192.168.1.7 上运行的名为 ups 的 UPS 实例。 powervalue 表示这个 UPS 的"电源冗余级别" —— 是我们依赖的几台 UPS 中的一台。如果你有多个 UPS,设置这个数字用于 MINSUPPLIES 的判断(系统至少需要多少电源供应才认为是安全的)。通常设为 1 即可。 username 用户名,用于连接远程 upsd 服务。这个用户必须在远程主机的 /etc/nut/upsd.users 中定义,并具有 MONITOR 权限。 password monuser 的密码,对应 upsd.users 中配置的密码。 (“primary”/“secondary”) 角色类型:secondary 表示这是一个从属客户端,不会主动发起关机,只会等待主控机通知或监听事件自行关机。常见角色是 primary(主控)和 secondary(从属)。
群晖的UPS默认名称就是 ups, 192.168.1.7
就是群晖的IP, 默认用户和密码为 monuser
,secret
。后面故障排除章节中也会有查看用户名密码的方法。
测试配置是否正确。
可以使用DEBUG模式启动运行一下,看看是否能正常工作。
sudo /usr/sbin/upsmon -D
如果正常,可以看到类似下面输出
Network UPS Tools upsmon 2.8.2 0.000000 fopen /run/nut/upsmon.pid: No such file or directory 0.000026 Could not find PID file to see if previous upsmon instance is already running! 0.000080 UPS: ups@192.168.1.7 (secondary) (power value 1) 0.000139 Using power down flag file /etc/killpower 0.000267 [D1] debug level is '1' 0.000615 [D1] Saving PID 1141184 into /run/nut/upsmon.pid 0.001801 [D1] Succeeded to become_user(nut): now UID=57 GID=57 Init SSL without certificate database 0.020004 upsnotify: failed to notify about state 2: no notification tech defined, will not spam more about it 0.020009 [D1] Trying to connect to UPS [ups@192.168.1.7] 0.021112 [D1] Logged into UPS ups@192.168.1.7
再使用
upsc
指令,查看一下 UPS 状态。upsc ups@192.168.1.7
会返回 UPS 的电量,版本等等信息。
Init SSL without certificate database battery.charge: 100 battery.charge.low: 10 battery.mfr.date: 2001/01/01 battery.runtime: 868 battery.runtime.low: 120 battery.type: PbAc battery.voltage: 13.7 battery.voltage.nominal: 12.0 device.mfr: American Power Conversion device.model: Back-UPS BK650M2-CH device.serial: 9Bxxxxxx device.type: ups driver.name: usbhid-ups driver.parameter.pollfreq: 30 driver.parameter.pollinterval: 5 driver.parameter.port: auto driver.parameter.synchronous: no driver.version: DSM7-2-1 driver.version.data: APC HID 0.96 driver.version.internal: 0.41 input.sensitivity: low input.transfer.high: 278 input.transfer.low: 160 input.voltage: 224.0 input.voltage.nominal: 220 ups.beeper.status: enabled ups.delay.shutdown: 20 ups.firmware: 294803G -292804G ups.load: 30 ups.mfr: American Power Conversion ups.mfr.date: 2022/10/25 ups.model: Back-UPS BK650M2-CH ups.productid: 0002 ups.realpower.nominal: 390 ups.serial: 9B2xxxxxxx ups.status: OL ups.test.result: Done and passed ups.timer.reboot: 0 ups.timer.shutdown: -1 ups.vendorid: 051d
启动并启用 NUT 服务:
sudo systemctl enable nut-monitor
sudo systemctl start nut-monitor
通知到企业微信
最后,我在 Linux 服务器上写了一个脚本,将 UPS 事件通知到企业微信。
- 在 Linux 服务器上创建通知脚本:
sudo vi /etc/ups/notify.sh
- 添加以下内容(记得替换
YOUR_KEY
为你的企业微信机器人密钥):
#!/bin/bash
WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
# 获取事件消息
EVENT_MSG="$1"
# 获取当前时间(格式:2025-05-10 18:30:12)
TIMESTAMP=$(date "+%F %T")
# 构造完整推送内容
MSG="[$TIMESTAMP] $EVENT_MSG"
# 发送消息到企业微信
curl -s -X POST "${WEBHOOK_URL}" \
-H 'Content-Type: application/json' \
-d "{
\"msgtype\": \"text\",
\"text\": {
\"content\": \"${MSG}\"
}
}" >/dev/null 2>&1
- 添加执行权限:
sudo chmod +x /etc/ups/notify.sh
- 测试脚本
/etc/ups/notify.sh 测试通知
- 编辑 upsmon 配置文件:
sudo vi /etc/ups/upsmon.conf
添加 NOTIFYCMD 指令指向你的脚本:
NOTIFYCMD /etc/ups/notify.sh
在 upsmon.conf 中启用你想要通知的事件,例如:
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOCOMM SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+EXEC
NOTIFYFLAG CAL SYSLOG+EXEC
NOTIFYFLAG NOTCAL SYSLOG+EXEC
NOTIFYFLAG OFF SYSLOG+EXEC
NOTIFYFLAG NOTOFF SYSLOG+EXEC
NOTIFYFLAG BYPASS SYSLOG+EXEC
NOTIFYFLAG NOTBYPASS SYSLOG+EXEC
- 重启 nut-monitor 服务:
sudo systemctl restart nut-monitor
现在,当 UPS 状态发生变化时,比如市电中断或恢复,你将同时在企业微信上收到通知。
断电测试
都配置好后,可以断开 UPS 电源测试一下。
如果此时你打开了群晖WEB,你会发现他会在配置的时间之后,会停止服务,进入安全模式。
随后,Linux服务器会关闭,如果此时你SSH连接着,你会看到
这说明我们配置已经正常工作了。
故障排除
- 如何查看日志文件
如果你遇到问题,可以查看以下日志文件:
- 在 Linux 上:
/var/log/messages
或journalctl -u nut-monitor
- 在群晖上:控制面板 > 日志中心 > 系统日志
- 群晖的UPS的配置和密码如何查看。
群晖的UPS配置需要 SSH 到群晖的后台才能看到。
/etc/ups/ups.conf
:查看UPS的名称和配置,如
[ups] # << 名称
driver = usbhid-ups # << 驱动
port = auto
/etc/ups/upsd.users
: 查看用户和密码,如
[monuser] # << 用户
password = secret # << 密码
upsmon master
你也可以修改这个密码,不过修改完成后需要重启 upsd 服务,使用下面命令重启
synosystemctl restart ups-usb
- 如果你的群晖开启了防火墙,记得放行 3493 端口。
- 如果你发现你的群晖没有正常关机,只是进入了待机模式,可以参考《市电断电时群晖用UPS实现自动关机的设置》修改一下关机指令。
总结
通过这个设置,我现在可以确保无论何时发生断电,我的群晖 NAS 和 Linux 服务器都能够安全关机,避免数据损坏和文件系统问题~