这是一个基于 Ubuntu Server 和 官方 CyberPower PowerPanel (pwrstat) 打造的 UPS 电源管理方案。专为监控 CyberPower OLS1000E 等系列 UPS 并在断电时优雅关闭 ESXi 主机及虚拟机而设计。
- 硬件解耦: 监控设备(ThinkPad T450 笔记本)通过笔记本内置电池独立供电,与 UPS 解耦,即使 UPS 耗尽电量也能持续运行监控逻辑。
- 企业级原生驱动: 由 CyberPower 官方
pwrstatd守护进程接管告警,消除开源轮询方案因协议适配不佳导致的不稳定。 - 断电重确认机制: 断电后进入可配置的延迟等待(默认 60s),期间多次调用
pwrstat反复确认,如市电恢复则自动终止关机。 - 全生命周期日志: 每次断电全程记录
[LIFECYCLE:*]结构化事件、UPS 状态快照、断电持续时长,日志同步写入文件和 systemd journal。 - 双保险硬件干预:
- 首选方法: SSH 到 ESXi 触发 Guest OS 优雅关机 (ACPI shutdown),随后关闭 ESXi 系统。
- 最终手段: 如果 SSH 故障/无响应,通过 IPMI (iDRAC) 强制切断电源,确保服务器硬件断电保全数据。
- 市电恢复检测:
ups-power-monitor服务持续轮询市电状态,恢复后自动记录断电持续时长,写入日志。 - 自动恢复开机: 市电恢复后自动通过 IPMI (iDRAC) 发送开机指令,等待 ESXi 启动后自动退出维护模式,实现无人值守全自动恢复。
graph TB
subgraph S_AC["市电供电"]
AC["🔌 市电 220V"]
end
subgraph S_UPS["CyberPower OLS1000E"]
UPS_IN["AC Input"]
UPS_BAT["🔋 UPS 电池"]
UPS_OUT["AC Output"]
UPS_USB["USB 通信口"]
end
subgraph S_T450["ThinkPad T450 - 监控端"]
T450_BAT["🔋 笔记本电池"]
T450_PWR["⚡ T450 电源"]
PWRSTATD["pwrstatd 守护进程"]
LOGGER["power-event-logger.sh"]
SHUTDOWN["shutdown.sh"]
MONITOR["power-restore-monitor.sh"]
HEALTH["healthcheck.sh"]
end
subgraph S_Dell["Dell R720XD - 受保护端"]
DELL_PWR["⚡ Dell 电源"]
ESXI["VMware ESXi"]
VMs["虚拟机群"]
IDRAC["iDRAC 8 Express"]
end
AC -->|供电| UPS_IN
UPS_IN --> UPS_OUT
UPS_BAT -.->|断电时切换| UPS_OUT
UPS_OUT -->|供电| T450_PWR
UPS_OUT -->|供电| DELL_PWR
UPS_USB -->|USB 状态通信| PWRSTATD
T450_BAT -.->|断电时独立供电| T450_PWR
PWRSTATD -->|pwrfail 事件| LOGGER
LOGGER -->|触发| SHUTDOWN
MONITOR -->|轮询检测恢复| LOGGER
SHUTDOWN -->|SSH 优雅关机| ESXI
SHUTDOWN -->|IPMI 降级关机| IDRAC
ESXI --> VMs
LOGGER -->|市电恢复 IPMI开机| IDRAC
style AC fill:#f9c74f,stroke:#f48c06,color:#000
style UPS_IN fill:#90be6d,stroke:#43aa8b,color:#000
style UPS_OUT fill:#90be6d,stroke:#43aa8b,color:#000
style T450_PWR fill:#577590,stroke:#277da1,color:#fff
style DELL_PWR fill:#f94144,stroke:#e63946,color:#fff
style IDRAC fill:#f94144,stroke:#e63946,color:#fff
flowchart TD
START(["⚡ 市电中断"])
START --> PWRSTATD["pwrstatd 检测到断电"]
PWRSTATD -->|延迟 60 秒| LOGGER["power-event-logger.sh"]
LOGGER --> SESSION["生成 Session ID & 记录 UPS 快照"]
SESSION --> SD["shutdown.sh 启动"]
SD --> DELAY{"断电重确认 等待 N 秒"}
DELAY -->|市电恢复| CANCEL(["✅ 取消关机"])
DELAY -->|仍在断电| SSH_CHECK{"ESXi SSH 可用?"}
SSH_CHECK -->|可达| GET_VMS["获取运行中 VM 列表"]
SSH_CHECK -->|不可达 120s 超时| IPMI_SOFT
GET_VMS --> SHUTDOWN_VMS["逐个关闭 VM"]
SHUTDOWN_VMS --> WAIT_VMS["等待 VM 全部停止 120s"]
WAIT_VMS --> MAINT["进入维护模式"]
MAINT --> SSH_ESXI["SSH 关闭 ESXi"]
SSH_ESXI --> WAIT60["等待 60s"]
style MAINT fill:#f9c74f,stroke:#f48c06,color:#000
WAIT60 --> CHECK_OFF{"IPMI 检查已关机?"}
CHECK_OFF -->|已关机| DONE(["✅ 关机完成"])
CHECK_OFF -->|仍在运行| IPMI_SOFT
IPMI_SOFT["IPMI Soft Power Off"]
IPMI_SOFT --> WAIT_SOFT{"等待超时后检查"}
WAIT_SOFT -->|已关机| DONE
WAIT_SOFT -->|仍未关机| IPMI_HARD
IPMI_HARD["⛔ IPMI Hard Power Off"]
IPMI_HARD --> VERIFY["验证关机状态"]
VERIFY --> DONE
style START fill:#e63946,stroke:#d62828,color:#fff
style CANCEL fill:#2a9d8f,stroke:#264653,color:#fff
style DONE fill:#2a9d8f,stroke:#264653,color:#fff
style IPMI_HARD fill:#e76f51,stroke:#e63946,color:#fff
sequenceDiagram
participant AC as 市电
participant UPS as UPS
participant PD as pwrstatd
participant LOG as event-logger
participant SD as shutdown.sh
participant ESXI as ESXi
participant VM as VM
participant IDRAC as iDRAC
participant MON as restore-monitor
Note over AC,MON: 阶段一 断电检测
AC-xUPS: 市电中断
UPS->>UPS: 切换至电池供电
UPS->>PD: USB: Power Failure
PD->>PD: 等待60秒
PD->>LOG: pwrfail事件
LOG->>LOG: 生成Session ID
LOG->>LOG: 记录UPS快照
LOG->>SD: 调用shutdown.sh
Note over AC,MON: 阶段二 延迟重确认
loop 每5秒 共N秒
SD->>PD: pwrstat -status
alt 市电恢复
SD-->>SD: 取消关机
else 仍断电
SD->>SD: 继续等待
end
end
Note over AC,MON: 阶段三 优雅关机
SD->>ESXI: SSH检查连通性
SD->>ESXI: SSH获取VM列表
ESXI-->>SD: 返回VM列表
loop 逐个VM
SD->>ESXI: SSH关闭VM
ESXI->>VM: ACPI关机
VM-->>ESXI: 关机完成
end
SD->>SD: 等待VM关闭 120s
SD->>ESXI: 进入维护模式
ESXI-->>SD: 维护模式已启用
SD->>ESXI: SSH关闭ESXi
SD->>SD: 等待60秒
SD->>IDRAC: IPMI power status
alt 已关机
IDRAC-->>SD: off
else 仍运行
SD->>IDRAC: IPMI power soft
SD->>SD: 等待超时
alt 仍未关机
SD->>IDRAC: IPMI power off 强制断电
end
end
Note over AC,MON: 阶段四 市电恢复
AC-->>UPS: 市电恢复
UPS->>UPS: 切回市电供电
loop 每10秒轮询
MON->>PD: pwrstat -status
PD-->>MON: Normal
end
MON->>LOG: active事件
LOG->>LOG: 记录断电时长
LOG->>IDRAC: IPMI power on
IDRAC->>ESXI: 服务器开机
Note over LOG,ESXI: 阶段五 退出维护模式
loop 等待ESXi SSH就绪 最长5分钟
LOG->>ESXI: SSH连接测试
end
LOG->>ESXI: 检查维护模式状态
ESXI-->>LOG: Enabled
LOG->>ESXI: 退出维护模式
ESXI-->>LOG: Disabled
ESXI->>VM: VM自动启动
LOG->>LOG: MONITORING_RESUMED
- 监控端: ThinkPad T450 笔记本,运行 Ubuntu 22.04,BIOS 配置上电自启,系统禁用休眠/挂起,7x24 运行。
- 受保护端: Dell PowerEdge R720XD(配备 iDRAC 控制器,IPMI over LAN 开启),运行 VMware ESXi。
- UPS: CyberPower OLS1000E,通过 USB 连接至 T450。
- 环境依赖:
- CyberPower PowerPanel for Linux (PPL): 必须事先使用 dpkg 安装(
sudo dpkg -i CyberPower_PPL_Linux...deb)并确认其服务已启动。 ipmitool、sshpass
- CyberPower PowerPanel for Linux (PPL): 必须事先使用 dpkg 安装(
ups-power-manager/
├── install.sh # 一键安装脚本
├── config/
│ ├── config.env # 主配置文件(ESXi / iDRAC / 参数)
│ └── logrotate.conf # 日志轮转配置(每周轮转,保留 12 周)
└── scripts/
├── shutdown.sh # 核心关机脚本(断电触发)
├── healthcheck.sh # 健康检查脚本(每小时定时运行)
├── power-event-logger.sh # 断电/恢复事件日志记录
├── power-restore-monitor.sh # 市电恢复轮询监控(常驻服务)
└── laptop-setup.sh # 监控端电源配置(禁用休眠等)
-
克隆本仓库到您的 Ubuntu 监控节点:
git clone https://github.com/erocat/ups-power-manager.git cd ups-power-manager -
确保 UPS USB 线已插好,测试 pwrstat 可正确读取 UPS 状态:
sudo pwrstat -status
-
修改
config/config.env,填入 ESXi 地址、iDRAC 地址及相应凭据;按需调整SHUTDOWN_DELAY(断电后观察等待秒数)。 -
以 root 权限执行一键安装(自动部署脚本、绑定 pwrstat 断电事件、注册 systemd 服务):
sudo ./install.sh
-
(首次部署) 配置监控端为永不休眠模式,并安装 logrotate 和 power-restore-monitor 服务:
sudo /opt/ups-power-manager/laptop-setup.sh sudo cp config/logrotate.conf /etc/logrotate.d/ups-power-manager # power-restore-monitor 由 install.sh 自动注册,或手动: sudo systemctl enable --now ups-power-monitor.service
⚠️ 还需在 BIOS 中手动设置After Power Loss → Power On以实现上电自启。
Level 1:Dry-Run(零风险,推荐先跑)
sudo /opt/ups-power-manager/shutdown.sh --dry-run不会发送任何关机指令,验证 SSH/IPMI 连通性和脚本逻辑。
Level 2:pwrstat 软件模拟(低风险)
sudo pwrstat -test触发真实断电事件流程,但 UPS 仍在供电。脚本会进入延迟等待,30 秒内 pwrstat 自动恢复 Normal 状态,脚本自动取消关机,不会实际关机。
Level 3:真实拔电测试(
直接将市电插头从 UPS 拔掉,触发完整的真实断电保护流程。
| 日志 | 路径/命令 | 内容 |
|---|---|---|
| 关机流程日志 | tail -f /var/log/ups-shutdown.log |
含 SESSION_ID 的完整关机步骤 |
| 电力事件日志 | tail -f /var/log/ups-power-events.log |
断电/恢复快照、持续时长 |
| systemd journal | journalctl -t ups-power-manager -f |
所有事件,支持时间过滤 |
按断电 Session 查询完整链路:
# 1. 先找 Session ID(格式:OUTAGE-YYYYMMDD-HHMMSS)
grep "LIFECYCLE:POWER_FAILURE" /var/log/ups-power-events.log
# 2. 用 Session ID 过滤完整流程
grep "OUTAGE-20260305-065407" /var/log/ups-shutdown.log生命周期关键事件标记:
LIFECYCLE:POWER_FAILURE_DETECTED 断电检测
LIFECYCLE:SHUTDOWN_START 关机流程入口
LIFECYCLE:DELAY_CHECK_START/DONE 延迟确认阶段
LIFECYCLE:VM_SHUTDOWN_START/DONE VM 关闭阶段
LIFECYCLE:ESXI_SSH_SHUTDOWN_START ESXi SSH 关机(含进入维护模式)
LIFECYCLE:IPMI_SOFT_START/FAILED IPMI Soft(降级路径)
LIFECYCLE:IPMI_HARD_START IPMI Hard(最终手段)
LIFECYCLE:SHUTDOWN_END 流程结束(含耗时)
LIFECYCLE:POWER_RESTORED 市电恢复
LIFECYCLE:OUTAGE_DURATION 本次断电持续时长
LIFECYCLE:AUTO_POWER_ON IPMI 自动开机
LIFECYCLE:EXIT_MAINTENANCE 退出 ESXi 维护模式(等待SSH→检查→退出)
LIFECYCLE:MONITORING_RESUMED 恢复正常监控
手动获取 UPS 快照:
sudo /opt/ups-power-manager/power-event-logger.sh snapshotpwrstat -status # UPS 当前状态
pwrstat -config # 断电事件绑定配置
systemctl status pwrstatd # pwrstatd 守护进程状态
systemctl list-timers ups-healthcheck.timer # 健康检查 timer 状态
systemctl status ups-power-monitor # 市电恢复监控服务状态
/opt/ups-power-manager/healthcheck.sh # 手动触发健康检查pwrstatd是整个方案的触发核心,务必确保它开机自启且正常运转:systemctl status pwrstatd。- T450 笔记本不会因断电而关机(
Enable shutdown system: Off),依靠笔记本内置电池维持运行,全程执行对 ESXi/iDRAC 的远程关机操作。 - T450 笔记本必须在 BIOS 中配置上电自启 (
After Power Loss → Power On),否则断电恢复后需要手动开机。 - 如需更改触发配置,使用
pwrstat -pwrfail -cmd <脚本路径> -duration <秒> -shutdown <on|off>设定。 - 如果需要重新配置笔记本节能设置,可重新运行
sudo /opt/ups-power-manager/laptop-setup.sh。
初次部署: 2026-03-05 14:38(UTC+8)
日志增强更新: 2026-03-05 15:25(UTC+8)
目标服务器: 192.168.1.117(主机名: ups,Ubuntu 6.8.0-100-generic)
| 路径 | 说明 |
|---|---|
/opt/ups-power-manager/shutdown.sh |
核心关机脚本(含 SESSION_ID + LIFECYCLE 标记) |
/opt/ups-power-manager/healthcheck.sh |
健康检查脚本 |
/opt/ups-power-manager/power-event-logger.sh |
断电/恢复事件日志(含 journal 同步) |
/opt/ups-power-manager/power-restore-monitor.sh |
市电恢复轮询监控(常驻服务) |
/opt/ups-power-manager/laptop-setup.sh |
服务器电源配置脚本 |
/opt/ups-power-manager/on-pwrfail.sh |
pwrstat 断电事件包装脚本(自动生成) |
/opt/ups-power-manager/on-active.sh |
pwrstat 市电恢复事件脚本(自动生成) |
/etc/ups-power-manager/config.env |
配置文件(权限 600) |
/etc/logrotate.d/ups-power-manager |
日志轮转配置 |
| 服务单元 | 类型 | 状态 | 说明 |
|---|---|---|---|
pwrstatd.service |
service | enabled / active | CyberPower 官方守护进程 |
ups-healthcheck.service |
service (oneshot) | enabled | 健康检查执行单元 |
ups-healthcheck.timer |
timer | enabled / active | 开机 2 分钟后首次运行,此后每小时执行 |
ups-power-monitor.service |
service | enabled / active | 市电恢复轮询检测,常驻运行 |
| 事件 | 延迟触发 | 脚本 | 脚本运行窗口 | 本机关机 |
|---|---|---|---|---|
pwrfail |
60 秒 | on-pwrfail.sh |
300 秒 | Off(T450 不关机) |
lowbatt |
立即 | shutdown.sh |
60 秒 | Off(T450 不关机) |
- ✅
pwrstatd正常运行,UPS 通信正常(OLS1000E 在线) - ✅
shutdown.sh --dry-run测试通过 - ✅
ups-healthcheck.timerenabled / active(开机自启) - ✅
ups-power-monitor.serviceenabled / active(市电恢复检测,开机自启) - ✅
laptop-setup.sh完成:休眠/挂起全部禁用,pwrstatd开机自启 - ✅ T450 断电不关机(
Enable shutdown system: Off) - ✅ 真实断电事件已验证记录(2026-03-05 06:54 UTC,电池 95%,持续约 30 分钟)
- ✅ logrotate 配置已安装(每周轮转,保留 12 周)
⚠️ pwrstat -active事件绑定不支持(当前 PPL 版本限制),已由ups-power-monitor.service轮询替代⚠️ BIOSAfter Power Loss → Power On需手动在服务器 BIOS 中设置
# 在服务器 192.168.1.117 上执行
pwrstat -status # UPS 当前状态
pwrstat -config # 断电事件绑定配置
systemctl status ups-power-monitor # 市电恢复监控服务
systemctl list-timers ups-healthcheck.timer # 健康检查 timer
journalctl -t ups-power-manager --since "1 hour ago" # 最近 1 小时所有事件
tail -f /var/log/ups-shutdown.log # 实时关机流程日志
tail -f /var/log/ups-power-events.log # 实时断电事件日志
/opt/ups-power-manager/shutdown.sh --dry-run # 测试关机链路(安全模式)