860 字
4 分钟
PVE 8+ 非标HID UPS开机启动与服务依赖故障修复全记录

在 Proxmox VE 8+(基于 Debian 12,使用 NUT 2.8+)环境下,接入山寨/公模 USB-HID 芯片(VID: 0001, PID: 0000)的 UPS 时,冷启动频繁出现 Error: Driver not connected 或 Connection refused,而开机后手动执行命令又能恢复。以下为该问题的完整原因剖析与彻底修复方案。


一、 根本原因剖析#

  1. nut-driver-enumerator 机制缺陷导致参数丢失
  • Debian 12 默认通过 /usr/libexec/nut-driver-enumerator.sh 动态生成 systemd 启动单元。
  • 该机制在冷启动解析非标单片机时,未能将 /etc/nut/ups.conf 中的关键变种协议参数(如 protocol = "hunnox")正确透传给驱动进程,导致驱动以默认规则匹配失败,抛出 Device not supported! 异常退出。
  1. IPC Unix Domain Socket 权限隔离
  • 驱动以 root 权限启动后,在 /var/run/nut/ 下生成的套接字文件(nutdrv_qx-ups)默认属组为 root:root(权限 0660)。
  • nut-server(upsd)以非特权用户 nut 运行,无法读取该套接字,直接抛出 Error: Driver not connected。
  1. systemd 依赖竞争与启动熔断(Race Condition)
  • 冷启动时主板 USB 控制器枚举与单片机初始化较慢,驱动在前几次快速重试失败后,容易撞上 systemd 的默认频率熔断机制(10秒内失败5次即永久停止重试)。
  • 若配置了硬依赖 Requires=nut-driver@ups.service,一旦驱动在启动最初的 1 秒内产生瞬时失败,nut-server 会直接判定依赖崩塌而进入 inactive (dead) 状态,导致端口未监听并抛出 Connection refused。

二、 修复步骤与命令清单#

步骤 1:固化驱动启动命令与 Socket 赋权#

绕过有缺陷的 enumerator 动态调用,直接指定验证成功的启动参数,并通过 ExecStartPost 自动将 IPC 套接字的属组开放给 nut 组。

Terminal window
mkdir -p /etc/systemd/system/nut-driver@ups.service.d
cat << 'EOF' > /etc/systemd/system/nut-driver@ups.service.d/override.conf
[Unit]
After=udev.service systemd-udev-settle.service
Wants=udev.service
[Service]
ExecStart=
ExecStart=/lib/nut/nutdrv_qx -u root -a ups
ExecStartPost=/bin/sh -c 'sleep 0.5; chown root:nut /var/run/nut/nutdrv_qx-ups; chmod 660 /var/run/nut/nutdrv_qx-ups'
Restart=always
RestartSec=3s
[Install]
WantedBy=multi-user.target
EOF

步骤 2:屏蔽 Enumerator 自动化服务与路径监听#

彻底关闭动态生成机制,防止系统在检测到配置变化时重写并破坏自定义配置:

Terminal window
# 屏蔽 enumerator 服务
systemctl stop nut-driver-enumerator.service 2>/dev/null || true
systemctl mask nut-driver-enumerator.service
# 屏蔽关联的 path 触发器
systemctl stop nut-driver-enumerator.path 2>/dev/null || true
systemctl mask nut-driver-enumerator.path

步骤 3:解耦服务依赖并配置服务端自愈#

将 nut-server 对驱动的强依赖(Requires=)降级为软依赖(Wants=),确保即便驱动因 USB 唤醒慢而延迟 1~2 秒,服务端也不会崩溃自杀,同时赋予服务端失败自愈能力:

Terminal window
mkdir -p /etc/systemd/system/nut-server.service.d
cat << 'EOF' > /etc/systemd/system/nut-server.service.d/override.conf
[Unit]
Wants=nut-driver@ups.service
After=nut-driver@ups.service
[Service]
Restart=on-failure
RestartSec=3s
EOF

步骤 4:使能开机自启并重载服务#

使各层服务注册进系统的开机自启链,并重载生效:

Terminal window
# 重载 systemd 配置
systemctl daemon-reload
# 重新拉起驱动及服务端
systemctl restart nut-driver@ups.service
systemctl restart nut-server
systemctl restart nut-client
# 确保开机自启启用
systemctl enable nut-driver@ups.service
systemctl enable nut-server
systemctl enable nut-client

三、 验证命令#

  1. 检查套接字文件所属权限:
Terminal window
ls -l /var/run/nut/nutdrv_qx-ups

预期输出:用户为 root,组为 nut,权限形如 srw-rw---- 1 root nut ...。 2. 验证驱动服务运行状态:

Terminal window
systemctl status nut-driver@ups.service

预期输出:状态显示绿色的 active (running),且 Drop-In 列表中包含 override.conf。 3. 测试数据通信:

Terminal window
upsc ups@localhost

预期输出:完整返回 battery.charge、input.voltage、ups.status: OL 等关键度量数据。 4. 冷启动终验:

Terminal window
reboot

重启完成后直接登录 Shell 执行 upsc ups@localhost,系统无需任何人工干预即可秒级获取数据。

PVE 8+ 非标HID UPS开机启动与服务依赖故障修复全记录
https://iiii.fun/posts/pve/pve-nut-hid-ups-boot-fix/
作者
庆灵
发布于
2026-10-02
许可协议
CC BY-NC-SA 4.0