3104 字
16 分钟

折腾家里云(二): 配置UPS系统,入手伊顿Eaton 9PX3000IRT2U和9PXEBM72RT2U电池包,并配置NUT共享网络UPS

半夜经历了一次停电之后,觉得学校供电稳定性实在是令人担忧。本文主要讲解了NUT (Network UPS Tools) 的架构和FSD通知机制并配置UPS,给局域网下的所有设备都提供网络UPS关机通知。

UPS基本参数信息#

类型参数
设备型号Eaton 9PX3000IRT2U
额定功率3000VA
电源架构在线式与互动式可切换
电池容量9PX3000IRT2U主机6只12V9Ah 铅酸电池
9PXEBM72RT2U电池包12只12V9Ah 铅酸电池
总计72V27Ah, 1944Wh
重量9PX3000IRT2U主机28kg
9PXEBM72RT2U电池包39.2kg
总计约67.2kg(含包装74kg)
价格海鲜市场 打包2000元含所有电池换新

装机#

小车运输
小车难以承受之重
电池包开箱
99新稀罕物
电池连接
比指头还粗的电池连接线
前面板界面
插上吹风机测试一下

配置UPS#

连接与识别#

我的 UPS 没有选装网络卡,所以用一根 USB type-B(打印机线)直接把 UPS 接到服务器上。

Terminal window
root@poweredge-r730:~# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:800a Intel Corp. Hub
Bus 001 Device 003: ID 413c:a001 Dell Computer Corp. Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 8087:8002 Intel Corp. 8 channel internal hub
Bus 002 Device 003: ID 0463:ffff MGE UPS Systems UPS <---这个

0463 是 MGE(后来被伊顿收购)的 USB Vendor ID,ffff 则是 UPS 类设备的通用 Product ID,伊顿/MGE 系的 UPS(9PX、5PX、5SC 等)基本都是这一对 ID。

为什么不用伊顿官方软件

伊顿官方的 Intelligent Power Protector (IPP) 配置全走 Web 界面,对”一台 UPS 通过局域网通知多台设备”这种多机联动支持得很差。而 NUT 是 Linux 世界的标准做法:配置全是纯文本,天然支持一台 UPS 共享给整个局域网。

NUT 架构#

NUT(Network UPS Tools)把”和 UPS 说话”和”要不要关机”这两件事拆成了两个独立的进程,中间用一套很简单的文本协议连接。

组件作用配置文件
驱动 usbhid-ups通过 USB HID 直接和 UPS 通信,把 UPS 的全部变量(电量、功率、状态……)暴露在一个 Unix socket 上ups.conf
upsd数据服务器,聚合各个驱动的数据,监听 TCP 3493 对外提供服务upsd.conf、upsd.users
upsmon监控 + 关机控制器,连到 upsd 判断”电还够不够”,不够就关机upsmon.conf
命令行工具upsc / upsrw / upscmd / upsdrvctl / upssched-
nut.conf总开关:standalone / netserver / netclient-
┌──────────────┐ USB (HID) ┌────────────────┐
│ Eaton 9PX │◀─────────────▶│ usbhid-ups │ ← 驱动
└──────────────┘ └───────┬────────┘
│ /run/nut/usbhid-ups-eaton9px
▼
┌─────────────┐
│ upsd │ ← 数据服务器
└──────┬──────┘
127.0.0.1:3493 ──────────────┤────────────── 10.10.10.2:3493
│ TCP 3493(NUT 明文协议)
┌───────────────────────────────┼───────────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ upsmon │ │ upsmon │ │ upsc / upsrw │
│ (primary) │ │ (secondary) │ │ 查询工具 │
│ R730 本机 │ │ fnOS NAS │ │ │
└───────────────┘ └───────────────┘ └───────────────┘

装包:

Terminal window
apt install nut nut-server nut-client

Debian 13 上装完会自动带上 systemd 集成:nut-driver-enumerator.path 会根据 ups.conf 自动生成 nut-driver@eaton9px.service,不需要手动启动驱动。

服务端配置(R730,MODE=netserver)#

nut.conf 里的 MODE 决定这台机器扮演什么角色:

/etc/nut/nut.conf
MODE=netserver
  • standalone:本机接 UPS、自己监控、自己关机(单机场景)
  • netserver:本机接 UPS,并把数据用 upsd 共享给局域网(本例)
  • netclient:本机不接 UPS,只连别人的 upsd(后文的二级节点)
ups.conf —— 驱动配置#
/etc/nut/ups.conf
[eaton9px]
driver = usbhid-ups
port = auto
vendorid = 0463
productid = ffff
desc = "Eaton 9PX UPS (USB)"
# UPS 收到断电指令后延迟 60 秒才切断输出(默认 20 秒),给服务器留更多关机时间
offdelay = 60
# 市电恢复后 90 秒再开启输出,尽量避免"刚关机就来电、来电又断电"的反复横跳
ondelay = 90

方括号里的 eaton9px 就是这台 UPS 在 NUT 里的标识名,后面 upsc、upsmon.conf 里都要用它,名字随意但必须一致。

port = auto 让驱动自己扫 USB 总线,所以 vendorid/productid 是必须写的,否则同一台机器上插了多个 USB HID 设备时可能认错。

offdelay / ondelay 到底在管什么

这两个值正常运行时完全不起作用,只在收到 killpower(断电指令)时才生效:

  • offdelay:收到断电指令后,UPS 再等多少秒才真正切断输出
  • ondelay:切断输出后,如果市电已经恢复,UPS 等多少秒后重新给负载上电
upsd.conf —— 监听地址#

默认 upsd 只监听 127.0.0.1,要让局域网里其它机器用上,必须显式加上本机在局域网中的地址:

/etc/nut/upsd.conf
LISTEN 127.0.0.1 3493
LISTEN 10.10.10.2 3493
upsd.users —— 用户与权限#

每个要连上来的 upsmon 都需要一个账号。这里有个反直觉的点:权限不用手写 actions,直接写 upsmon primary / upsmon secondary 即可,NUT 会自动赋予当前版本所需的全部权限(手写容易漏,升级后还可能失效)。

/etc/nut/upsd.users
# 本机 upsmon,是 primary,需要设置 FSD 的权限
[upsmon]
password = <你的密码>
upsmon primary
# 二级节点(NAS),只需要能登录读取状态
[fnos-upsmon]
password = <你的密码>
upsmon secondary
[cyan-fnos-upsmon]
password = <你的密码>
upsmon secondary

两者最核心的差别:只有 primary 类型的用户有 FSD 权限,也就是只有它能把”强制关机”标志写进 upsd。二级节点只能被动接收。

upsmon.conf —— 监控与关机#
/etc/nut/upsmon.conf
MONITOR eaton9px@localhost 1 upsmon <密码> primary
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 180
DEADTIME 15
POWERDOWNFLAG "/etc/killpower"
OFFDURATION 30
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5

MONITOR 那行的五个参数依次是:<UPS标识> <供电路数> <用户名> <密码> <角色>。

其中**供电路数(powervalue)**值得单独说:它表示”这台机器有几路电源来自这个 UPS”。R730 是单电源,所以填 1;带双电源的机器就要填 2。它和 MINSUPPLIES 配合构成关机判据——当”健康供电的路数 < MINSUPPLIES”时才会触发关机。

官方文档里还有一个特殊的用法:powervalue 填 0 表示”这台机器不从被监控的 UPS 取电,但仍想看它的状态”,这需要配合 MINSUPPLIES 0 使用(否则会因为”可用路数 0 < 1”反而触发关机),这就是所谓的只监控不关机模式。

其余参数:

参数值含义
MINSUPPLIES1至少要有 1 路可靠供电,否则关机
SHUTDOWNCMD/sbin/shutdown -h +0真正执行的关机命令
POLLFREQ5正常状态下每 5 秒拉一次状态
POLLFREQALERT5电池供电时每 5 秒拉一次状态
HOSTSYNC180primary 置 FSD 后,等待 secondary 断开的最长时间
DEADTIME15多久收不到状态就把 UPS 标记为 dead(必须是 POLLFREQ 的整数倍)
POWERDOWNFLAG/etc/killpower关机时创建的标志文件,见后文
OFFDURATION30忽略”短暂 OFF 状态”的秒数,避免校准/切换瞬间被误判为断电
RBWARNTIME43200多久提示一次”电池该换了”
NOCOMMWARNTIME300多久提示一次”联系不上 UPS”
FINALDELAY5发出关机通知后,等 5 秒再执行 SHUTDOWNCMD
HOSTSYNC 不是越大越好

HOSTSYNC 是 primary 等二级节点断开的时间,它和二级节点的 FINALDELAY 有耦合关系:

如果二级节点的 FINALDELAY 大于 primary 的 HOSTSYNC,primary 会放弃等待该二级节点。

而这段时间是拿电池换来的。默认的 15 秒对 NAS 关机来说太紧(fnOS 上还跑着 Docker),所以我改成了 180 秒,剩余电量完全撑得住。

让 UPS 在服务器关机后也断电#

这一步是很多人会漏掉的:服务器关机了,但 UPS 还在放电。如果停电时间很长,电池会被彻底耗干;如果”关机后立刻来电”,服务器又会在电池剩一点点的时候启动,接着再停一次电——这就是所谓的 power race。

NUT 的解法是三级配合:

  1. upsmon 判定要关机时,创建 POWERDOWNFLAG 文件(本例是 /etc/killpower)
  2. 系统关机走到最后,systemd 会执行 /usr/lib/systemd/system-shutdown/nutshutdown
  3. 该脚本先用 upsmon -K 检查标志文件是否存在,存在就调用 upsdrvctl shutdown 命令 UPS 切断输出(延迟 offdelay 秒)
Terminal window
# 手动检查标志文件状态,正常运行时应当输出 "Power down flag is not set"
upsmon -K

之后只要市电恢复,UPS 会在 ondelay 秒后自动给负载上电,服务器再依靠 BIOS 的”上电自启”(R730 里是 AC Power Recovery)自动开机。

FSD:一次断电通知背后的完整流程#

FSD 是 Forced Shutdown(强制关机),是 NUT 里最巧妙的一个设计。关键点在于:primary 并不是”挨个通知”二级节点的,而是把 FSD 标志写进 upsd,所有连上来的 upsmon 自己会看到。

在 upsd 看来,FSD 标志等价于”市电断电 + 电池低电量”,也就是 critical 状态。所以从二级节点的视角,“UPS 真的快没电了”和”primary 让我关机”是同一件事,走的是同一套逻辑:

断电流程示意图
断电流程示意图

几个容易踩的点:

  1. 只有 upsmon primary 用户有 FSD 权限。 如果二级节点连上来的账号被误配成 primary(或反之),就会表现为”通知发出去了但没人关机”或”该等的没等”。
  2. HOSTSYNC 与 FINALDELAY 的配对(见上一节)。
  3. SHUTDOWNEXIT 默认为 yes:二级节点一旦开始执行 SHUTDOWNCMD,upsmon 就会退出,从而断开与 upsd 的连接;primary 正是靠着”客户端一个个掉线”来判断二级节点是否已经进入关机流程。所以如果某台二级节点关机特别慢(比如 NAS 要停 Docker),要么调大 primary 的 HOSTSYNC,要么用 upssched 让它更早开始关机。
  4. upsmon -c fsd 会立刻走完整流程(包括让机器关机),演练时请慎用。

二级节点(fnOS / NAS)配置#

二级节点不接 UPS,也不需要驱动,只要装 nut-client(提供 upsmon)即可:

Terminal window
apt install nut-client
/etc/nut/nut.conf
MODE=netclient
/etc/nut/upsmon.conf
# 用户名密码要和 R730 上 /etc/nut/upsd.users 里的完全一致
MONITOR eaton9px@10.10.10.2 1 fnos-upsmon <密码> secondary
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
FINALDELAY 5
NOTE

POWERDOWNFLAG 在 secondary 上其实没有意义——二级节点没有驱动,无法命令 UPS 断电,nutshutdown 会因为找不到 upsdrvctl 而跳过这一步。不配置它也没问题,只要保证 SHUTDOWNCMD 正确即可。

验证连通性:

Terminal window
# 在二级节点上列出能看到哪些 UPS
upsc -l 10.10.10.2
# 读取关键变量
upsc eaton9px@10.10.10.2 ups.status battery.charge battery.runtime

如果报 Access denied,八成是 upsd.users 里没有对应的用户名/密码,或者 upsd.conf 里少了一行 LISTEN。

日常使用:几个常用命令#

Terminal window
upsc eaton9px # 打印全部 102 个变量
upsc eaton9px ups.status battery.charge battery.runtime ups.load
upsc -l # 列出本机 upsd 能看到的 UPS
upsrw -l eaton9px # 列出可写变量
upscmd -l eaton9px # 列出支持的即时命令
upscmd eaton9px beeper.mute # 静音(半夜停电时你会用到的)
upscmd eaton9px test.battery.start.quick # 手动启动一次电池自检
upsmon -c reload # 重载 upsmon.conf

实测这台 9PX3000IRT2U 在 12% 负载(约 320W)下的状态:

Terminal window
$ upsc eaton9px | grep -E "ups.status|battery.charge:|battery.runtime:|ups.load|ups.realpower:"
battery.charge: 100
battery.runtime: 11803 # ≈ 3 小时 16 分
ups.load: 12
ups.realpower: 320
ups.status: OL CHRG
ups.status 的常见组合

ups.status 可能是多个 flag 的组合,用空格分隔,常见的有:

flag含义
OLOn Line,市电在线
OBOn Battery,电池供电
LBLow Battery,低电量(触发关机的关键)
CHRG / DISCHRG充电中 / 放电中
BYPASS旁路供电(有电但不受保护)
FSD已收到强制关机指令
OVER过载
CAL电池校准中
fnos UPS管理界面1
飞牛UPS管理
fnos UPS管理界面2

监控:把状态推到 Uptime Kuma#

光有日志还不够,我需要”手机能收到告警”。upsmon 默认只会在 syslog 和终端 wall 里喊(NOTIFYFLAG 的默认行为),要自己写 NOTIFYCMD 才能推送到手机。所以写了个常驻脚本,把状态变化推到 Uptime Kuma 的 Push 监控:

/etc/systemd/system/nut-ups-push.service
[Unit]
Description=NUT UPS status push to Uptime Kuma
Wants=network-online.target
After=network-online.target nut-server.service
[Service]
Type=simple
ExecStart=/usr/local/bin/nut-ups-push.sh
Restart=always
RestartSec=15
Environment="LOG_FILE="
[Install]
WantedBy=multi-user.target

脚本逻辑很简单:每 5 秒 upsc 一次,把状态归并成 online / battery / lowbatt / bypass / commbad 几种模式,模式一变就立即推送;一直正常时则每 10 分钟推一次心跳。推送内容带上当前功率、电池百分比和预计剩余时间:

通知1通知2
邮件通知

实测记录#

截至写这篇文章时,这套系统已经挡下了几次停电:

时间事件结果
2026-09-06 14:15停电,转电池供电75 分钟后恢复,未触发关机
2026-09-06 15:33再次停电5 秒后恢复
2026-09-22 20:10停电,转电池供电12 分钟后恢复
你应该致电国家电网

参考#

networkupstools
/
nut
Waiting for api.github.com...
00K
0K
0K
Waiting...
折腾家里云(二): 配置UPS系统,入手伊顿Eaton 9PX3000IRT2U和9PXEBM72RT2U电池包,并配置NUT共享网络UPS
https://www.mintlab.top/posts/tries/eaton9px_nut_setup/
作者
Mint
发布于
2026-09-25
许可协议
CC BY-NC-SA 4.0
发表评论

输入用户名和邮箱后自动检查登录状态。登录后用户名和邮箱将被绑定, 只可以修改头像和主页链接。

未登录
昵称
邮箱
填写头像链接与主页链接

头像链接为空默认使用gravatar头像

头像
主页
人机验证
评论列表

以下是可爱的评论们:

暂无评论, 呜呜, 快来评论喵!