UPS 断电后,怎么让 Homelab 自动关机

upsc ups@localhost 已经能读到 UPS 状态时,真正要先定下来的是“断电后等多久再关机”。

UPS 不是为了让机器一直硬撑,而是为了留出几分钟,让服务停止、数据落盘、虚拟机或容器有序退出。对 NAS、数据库、下载任务混跑的主机来说,这几分钟通常比额外续航更重要。

先定规则,再写脚本

自动关机最怕触发过早,也怕触发过晚。

如果市电只闪断几秒,马上关机会影响使用;如果一直等到电池接近耗尽,可能又来不及写盘。更实用的做法是先定一个简单规则:

  1. 检测到 UPS 进入电池供电状态
  2. 连续保持 60 到 180 秒后再检查一次
  3. 如果仍未恢复市电,执行关机流程
  4. 如果电量低于阈值,例如 30%,直接关机

这里的关键参数只有两个:

  • 延迟时间:给短时停电留缓冲
  • 电量阈值:避免拖到来不及安全退出

常见实现:NUT + 短脚本

NUT(Network UPS Tools)用于读取 UPS 状态。很多 USB UPS 可以接入,但不同型号的驱动名、变量名可能不同,配置前需要按设备实际输出确认;以下示例未验证适用于所有设备。

如果系统已经能读取 UPS 信息,脚本可以很短。下面这个例子只做一件事:当设备仍处于电池供电,且电量低于阈值时执行关机。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env bash
set -euo pipefail

UPS_NAME="ups@localhost"
LOG_FILE="/var/log/ups-auto-shutdown.log"

STATUS="$(upsc "$UPS_NAME" ups.status 2>/dev/null || echo UNKNOWN)"
CHARGE="$(upsc "$UPS_NAME" battery.charge 2>/dev/null || echo 100)"

echo "$(date '+%F %T') status=$STATUS charge=$CHARGE" >> "$LOG_FILE"

if [[ "$STATUS" == *"OB"* ]]; then
if [[ "${CHARGE:-100}" -le 30 ]]; then
echo "$(date '+%F %T') low battery, shutdown now" >> "$LOG_FILE"
/sbin/shutdown -h now
fi
fi

OB 通常表示设备处于电池供电状态。这个脚本没有实现“等待 120 秒”的逻辑,更适合配合 systemd 定时器,或者由 NUT 事件机制触发。

比触发更重要的是关机顺序

只解决“何时执行 shutdown”还不够,真正容易出问题的是关机前先停谁。

一个更实用的顺序通常是:

先停写入频繁的服务

例如下载、同步、数据库、媒体索引。这类服务持续写盘,硬断电风险更高。

再停容器或虚拟机

容器可以用 docker stop,虚拟机则按实际平台处理。这里优先保证有序退出,不必为了极端完整的优雅流程把逻辑写得过重。

最后关宿主机

如果宿主机先关,内部服务会被直接中断。

可以把停服务流程拆成独立脚本,主脚本只负责触发:

1
2
3
4
5
6
#!/usr/bin/env bash
set -e

/usr/bin/docker stop app1 app2 || true
/usr/bin/systemctl stop example.service || true
/sbin/shutdown -h now

两个容易忽略的坑

1. 不要只看断电,也要处理恢复

有些环境会反复闪断。如果脚本每次检测到电池供电都重新计时,逻辑可能变乱。更稳妥的方式是:

  • 进入电池模式时只触发一次
  • 市电恢复时取消待执行任务

2. 不要假设所有 UPS 字段都存在

不同设备暴露的变量并不一致。有的能读到 battery.runtime,有的只能读到 battery.charge。脚本里应该提供默认值,并把失败情况写入日志,便于停电后核对流程是否真的执行。

一个够用的落地方案

如果不想一开始就做复杂编排,可以先用最小可用方案:

  • UPS 通过 USB 接到主机
  • 系统可以稳定读取 UPS 状态
  • 断电持续 2 分钟后关机
  • 电量低于 30% 时强制关机
  • 关机前停掉最关键的 1 到 3 个服务

这已经能覆盖多数家用单机场景。先把单机安全关机跑通,再考虑通知、联动其他节点、统一编排。

一个边界:来电自动开机不由脚本决定

“断电后自动关机”和“来电后自动恢复”不是同一件事。

前者主要依赖系统和脚本;后者通常取决于 BIOS/UEFI 中的 AC Power Recovery 一类选项。脚本只能负责有序停机,不能决定主板在来电后是否自动开机,这一项需要到固件设置里确认。

可以先检查这三项

  1. upsc 是否能稳定读到状态
  2. 关机前要停的服务是否已经列清楚
  3. 主板是否支持来电自启

如果还没开始配置,先把“必须先停的服务列表”写出来,通常比继续加长脚本更有用。


UPS 断电后,怎么让 Homelab 自动关机
https://ghost.kasumi.live/2026/03/15/UPS 断电后,怎么让 Homelab 自动关机/
作者
Amadeus
发布于
2026年3月15日
许可协议