1. 项目概述:为边缘计算设备构建电力“哨兵”
最近在折腾一个部署在工厂车间的边缘计算项目,用的是Jetson Orin NX核心的reComputer r1000。这机器性能没得说,跑视觉检测模型杠杠的,但车间环境你懂的,电压不稳、偶尔跳闸是家常便饭。机器突然断电,不仅可能导致正在处理的数据丢失,更麻烦的是可能损坏文件系统,重启后一堆服务起不来,还得人工跑现场,费时费力。
于是,给这台reComputer r1000配个UPS(不间断电源)就成了刚需。但光是配个UPS还不够,我更希望设备自己能“感知”外部供电状态。比如,当市电断开,UPS开始供电时,设备能立刻知道“哦,我现在在用电池了”,然后自动触发一系列降级或保存操作;或者,能实时读取UPS的输入电压,一旦电压异常波动,就提前告警。这就像是给设备装了一个电力“哨兵”,让它对供电环境心中有数。
市面上大多数UPS都支持通过USB或串口与主机通信,但如何让reComputer r1000(本质上是台运行Ubuntu的ARM设备)正确识别UPS、读取数据,并写成可靠的后台服务,这里面有不少细节。网上资料比较零散,要么是针对x86 PC的,要么只讲了一半。我把自己从选型、接线、调试到写成系统服务的完整过程梳理出来,尤其是ARM架构下的一些坑,希望能帮到有类似需求的朋友。
2. 核心思路与方案选型
给单板计算机或嵌入式设备接UPS,核心目标是实现状态监控与自动控制。通常有两种主流思路:
思路一:UPS网络管理卡(SNMP/HTTP)一些高端UPS会配备网络管理卡,设备可以通过网络协议(如SNMP)查询UPS状态。这种方式不依赖主机USB驱动,更灵活,但硬件成本高,且配置相对复杂。
思路二:USB/串口直连 + 监控软件这是最经济、最通用的方案。UPS通过标配的USB数据线(或选配的串口线)直接连接到主机,主机上运行一个监控守护进程(如nut),该进程通过驱动与UPS通信,解析数据,并提供本地或网络服务接口。
对于reComputer r1000这样的边缘设备,思路二无疑是首选。它成本低、通用性强,而且软件生态成熟。这里的关键是软件选型。
2.1 为什么选择 NUT (Network UPS Tools)
在Linux世界里,管理UPS的软件主要有两个:apcupsd和nut。
- apcupsd: 历史悠久,对APC品牌UPS支持极好,配置简单。但它的设计更偏向于“一台电脑配一台APC UPS”,对其他品牌的支持可能通过通用驱动实现,灵活性和功能上有时不如nut。
- NUT (Network UPS Tools): 这是一个功能强大、支持厂商极其广泛的开源项目。它的架构非常清晰,分为驱动层(
upsdrv)、服务层(upsd)和客户端层(upsc,upsmon等)。它原生支持多台设备监控一台UPS,或者一台设备监控多台UPS,非常适合复杂的部署场景。
考虑到车间环境未来可能扩展,以及UPS品牌的不确定性(这次用的是山特,下次可能是其他品牌),NUT的通用性和灵活性优势明显。因此,我决定采用NUT方案。
2.2 系统架构与数据流
整个方案的逻辑架构是这样的:
[山特 UPS] --(USB数据线)--> [reComputer r1000] | v [NUT UPS Driver (usbhid-ups)] | v [NUT Daemon (upsd)] / | \ / | \ v v v [状态查询(upsc)] [事件监控(upsmon)] [网络客户端] | | | v | [执行关机脚本] v [我们自定义的电压读取脚本]- 驱动层:
usbhid-ups驱动负责与USB连接的UPS直接对话,读取其发送的原始数据。 - 服务层:
upsd守护进程作为服务器,管理驱动,并将解析后的标准化数据(如电压、负载、电池电量)通过本地套接字或网络端口提供服务。 - 客户端层:
upsc:命令行工具,用于即时查询UPS的任意状态变量。upsmon:监控守护进程。它持续查询upsd,当检测到特定事件(如市电断电、电池电量低)时,可以触发预定义的动作,最核心的就是安全关闭系统。- 我们自定义的脚本或应用程序,可以通过调用
upsc或直接连接upsd服务来获取数据,例如实现一个实时读取输入电压并写入日志或推送告警的功能。
我们的目标“读取输入电压”,最终就会落在通过upsc或 NUT 提供的编程接口(如Python的nut2库)来获取input.voltage这个状态变量上。
3. 在 reComputer r1000 上部署 NUT
reComputer r1000 预装了 JetPack 5.x/6.x,其底层是 Ubuntu 20.04/22.04 LTS。以下操作基于 Ubuntu 22.04,但流程具有通用性。
3.1 安装 NUT 软件包
首先,通过APT包管理器安装NUT。注意,NUT在Ubuntu仓库中有三个相关包:
nut:客户端和基础工具。nut-server:包含驱动和服务端守护进程。nut-client:客户端工具。
为了完整功能,我们安装服务端和客户端:
sudo apt update sudo apt install nut-server nut-client nut安装过程中可能会询问是否用dbus或serial启动驱动,对于USB UPS,通常保持默认或选择“No”即可,因为我们会手动配置。
注意:在ARM架构的Jetson平台上,确保你的APT源是正常的。有时需要配置NVIDIA的L4T仓库。如果
apt install失败,可以先运行sudo apt update && sudo apt upgrade更新系统。
3.2 连接UPS并确认设备识别
在配置之前,先将UPS的USB数据线连接到reComputer r1000的USB端口上。然后,检查系统是否识别了该设备。
1. 使用lsusb命令查看
lsusb在输出列表中,寻找类似于“American Power Conversion”或“EATON”或“SANTAK”的条目。例如,我使用的山特UPS可能显示为:
Bus 001 Device 004: ID 0665:5161 Cypress Semiconductor USB to Serial这里的ID 0665:5161是关键。记下这个ID,或者直接看厂商/产品描述。
2. 检查内核是否加载了USB HID驱动USB UPS通常被识别为HID设备。检查/proc/bus/input/devices或使用dmesg查看最新日志:
dmesg | tail -20如果连接成功,你应该能看到类似usb 1-2.1: new low-speed USB device number 4 using xhci_hcd以及input: SANTAK UPS as /devices/.../input/inputXX的信息。
3. 确认设备节点USB HID UPS通常会在/dev下创建节点,可能是/dev/usb/hiddev0或/dev/hidraw0。更通用的方法是,NUT驱动会尝试与USB设备直接通信,不一定需要特定的设备节点。但我们可以确认UPS是否在HID设备列表中:
sudo ls -la /dev/usb/或者检查是否有hidraw设备:
ls -la /dev/hidraw*实操心得:不同品牌、不同型号的UPS,被系统识别的方式可能略有差异。
lsusb能识别是第一步。如果lsusb里完全看不到疑似UPS的设备,首先检查USB线是否完好,尝试更换USB口(特别是尝试连接到机器本体的USB口,而非经过扩展坞)。有些老式UPS可能需要特定的USB转串口芯片驱动,但在Linux内核中大多已集成。
3.3 配置 NUT
NUT的配置文件主要位于/etc/nut/目录下。我们需要配置三个主要文件:nut.conf,ups.conf, 和upsd.conf。upsmon.conf用于关机控制,我们稍后配置。
1. 配置运行模式 (/etc/nut/nut.conf)这个文件很简单,只定义NUT的运行模式。对于我们这种“一台电脑监控一台直接连接的UPS”的场景,模式应设为standalone。
sudo vim /etc/nut/nut.conf将内容修改为:
MODE=standalone2. 配置UPS设备 (/etc/nut/ups.conf)这是核心配置,告诉NUT:有一台什么样的UPS,用什么驱动,连接在哪里。
sudo vim /etc/nut/ups.conf添加以下内容(请根据你的UPS品牌型号调整):
[santak] driver = usbhid-ups port = auto desc = "SANTAK UPS in Workshop" # vendorid = 0665 # 如果需要,可以指定从lsusb获取的VID # productid = 5161 # 如果需要,可以指定从lsusb获取的PID[santak]:这是你为这台UPS定义的名称(upsname),后续查询、监控都会用到这个名字。可以自定义,如workshop_ups。driver = usbhid-ups:这是用于大多数USB HID协议UPS的通用驱动,对山特、APC、伊顿等主流品牌支持良好。port = auto:让驱动自动搜索连接的UPS。这是最省事的方式。如果自动识别失败,可以尝试指定具体的设备路径,如port = /dev/usb/hiddev0。desc:描述信息,可选。vendorid和productid:通常不需要,auto模式能搞定。如果系统连接了多个HID设备,可以指定这两个ID来精确匹配。
重要提示:如何确定
driver参数?NUT支持上百种驱动。最佳方法是查阅NUT的硬件兼容性列表(可在其官网或/usr/share/nut/driver.list查看),或者使用nut-scanner工具自动探测:sudo nut-scanner -U这个命令会扫描USB设备并给出推荐的驱动配置片段,非常有用。
3. 配置 upsd 服务 (/etc/nut/upsd.conf)upsd是守护进程,需要配置它监听的地址和访问控制。
sudo vim /etc/nut/upsd.conf确保有以下行(默认可能已存在或部分存在):
LISTEN 127.0.0.1 3493 LISTEN ::1 3493这表示upsd只监听本地回环地址(localhost)的3493端口,这样更安全。如果你需要从网络上的其他机器查询这台UPS,则需要添加LISTEN 0.0.0.0 3493,但务必配合下面的用户认证。
4. 配置 upsd 用户 (/etc/nut/upsd.users)为了安全,需要创建用户来访问upsd服务。我们将创建一个用于监控关机的用户和一个用于普通查询的用户。
sudo vim /etc/nut/upsd.users添加如下内容:
[monmaster] password = your_strong_password_here upsmon master [queryuser] password = another_strong_password actions = GET instcmds = LIST[monmaster]:这个用户将被upsmon进程使用,权限是upsmon master,意味着它有权限命令UPS关机,并代表主控系统。[queryuser]:这个用户用于普通的状态查询(我们读取电压就用这个),权限较低,只有GET(获取变量)和LIST(列出变量)的权限。
安全提醒:务必使用强密码替换
your_strong_password_here和another_strong_password。并且,如果upsd监听了非本地地址,强密码至关重要。
5. 配置 upsmon 监控 (/etc/nut/upsmon.conf)upsmon是监控进程,负责在UPS状态异常时执行动作。
sudo vim /etc/nut/upsmon.conf找到并修改以下关键行:
MONITOR santak@localhost 1 monmaster your_strong_password_here masterMONITOR:监控指令。santak@localhost:格式为upsname@hostname:port。santak是我们在ups.conf里定义的UPS名,localhost是运行upsd的主机,3493是默认端口可省略。1:表示此UPS连接的系统是“主电源”,数字1代表权重,在多个UPS的配置中更有用,这里设为1即可。monmaster和your_strong_password_here:使用在upsd.users中为upsmon创建的用户和密码。master:表示这台主机是受此UPS保护的主系统(相对于网络中的从属监控节点)。
接着,配置关机指令。找到SHUTDOWNCMD一行,通常默认是:
SHUTDOWNCMD "/sbin/shutdown -h +0"这表示当需要关机时,执行shutdown -h now。在基于systemd的现代系统(如Ubuntu 22.04)上,可能需要使用systemctl或确保shutdown路径正确。保持默认通常可以工作。
6. 设置权限NUT驱动需要以特定用户(通常是nut)身份访问USB设备。我们需要将设备节点的所有者改为nut用户所在的组(通常是nut组)。 首先,查看你的UPS设备节点(假设是/dev/hidraw0):
ls -l /dev/hidraw0输出可能类似crw-rw---- 1 root root 242, 0 May 1 10:00 /dev/hidraw0。 然后,将其组所有权改为nut,并赋予组读写权限:
sudo chown root:nut /dev/hidraw0 sudo chmod 660 /dev/hidraw0为了使更改永久生效(避免每次重启后重新设置),可以创建一个UDEV规则。
sudo vim /etc/udev/rules.d/99-nut-ups.rules加入以下内容(请将ATTRS{idVendor}=="0665", ATTRS{idProduct}=="5161"替换为你从lsusb中获取的实际VID和PID):
SUBSYSTEM=="usb", ATTRS{idVendor}=="0665", ATTRS{idProduct}=="5161", GROUP="nut", MODE="0660" SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0665", ATTRS{idProduct}=="5161", GROUP="nut", MODE="0660"保存后,重新加载UDEV规则并重启相关服务:
sudo udevadm control --reload-rules sudo udevadm trigger3.4 启动服务与测试
1. 启动驱动首先启动UPS驱动,它会尝试连接UPS并注册到upsd。
sudo systemctl start nut-driver检查驱动状态和日志:
sudo systemctl status nut-driver sudo tail -f /var/log/syslog | grep -i ups如果成功,你会在日志中看到类似usbhid-ups: Startup successful和santak: Connected to UPS [santak]的信息。
2. 启动 upsd 服务驱动正常运行后,启动upsd服务。
sudo systemctl start nut-server # 在有些系统上,服务名可能是 nut-server # 或者明确启动 upsd sudo systemctl start upsd检查状态:
sudo systemctl status upsd3. 使用 upsc 测试查询现在,我们可以使用upsc命令查询UPS的所有状态变量了。这是验证配置是否成功的关键一步。
upsc santak@localhost如果一切正常,你会看到一长串输出,类似于:
battery.charge: 100 battery.runtime: 2800 input.voltage: 227.0 input.voltage.nominal: 220 output.voltage: 230.0 ups.status: OL ...battery.charge:电池当前电量百分比。battery.runtime:电池剩余续航时间(秒)。input.voltage:这就是我们最关心的UPS输入电压(即市电电压)。output.voltage:UPS输出电压。ups.status:UPS状态。OL表示在线(On Line,市电正常),OB表示在电池上(On Battery,市电断开)。
如果upsc命令返回Error: Connection failure: Connection refused,说明upsd服务没有正常运行,或者认证失败。请检查upsd服务状态和日志。
4. 启动 upsmon 并设置开机自启测试成功后,启动监控进程并启用所有NUT服务开机自启。
sudo systemctl start nut-monitor # 或 sudo systemctl start upsmon sudo systemctl enable nut-driver nut-server nut-monitor4. 实现输入电压的读取与监控
基础服务搭好了,现在来实现我们的核心目标:持续、可靠地读取UPS的输入电压,并加以利用。
4.1 使用 Shell 脚本定时读取与记录
最简单的方式是写一个Shell脚本,利用upsc命令获取input.voltage,然后记录到文件或数据库中。
创建一个脚本文件,例如/usr/local/bin/read_ups_voltage.sh:
#!/bin/bash # 定义UPS名称和主机 UPS_NAME="santak@localhost" # 定义日志文件路径 LOG_FILE="/var/log/ups_voltage.log" # 获取当前时间戳 TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') # 使用upsc获取输入电压,过滤出数值 INPUT_VOLTAGE=$(upsc $UPS_NAME input.voltage 2>/dev/null) # 检查是否成功获取到电压值 if [[ -n "$INPUT_VOLTAGE" ]]; then echo "$TIMESTAMP - Input Voltage: ${INPUT_VOLTAGE} V" >> "$LOG_FILE" else echo "$TIMESTAMP - ERROR: Failed to read input voltage from UPS" >> "$LOG_FILE" fi给脚本添加执行权限:
sudo chmod +x /usr/local/bin/read_ups_voltage.sh然后,你可以通过cron定时任务来定期执行这个脚本。例如,每分钟记录一次:
sudo crontab -e在cron配置文件中添加一行:
* * * * * /usr/local/bin/read_ups_voltage.sh这样,每分钟就会在/var/log/ups_voltage.log中记录一条电压数据。你可以用tail -f /var/log/ups_voltage.log来实时查看。
4.2 使用 Python 脚本进行高级监控与告警
对于更复杂的逻辑,比如电压超出阈值时发送告警,Python是更好的选择。我们可以使用python3-nut2这个库(如果可用),或者直接解析upsc命令的输出。
首先,安装必要的库(如果使用nut2):
sudo apt install python3-pip pip3 install nut2 --user # 或者使用系统包管理器尝试安装 python3-nut2 (可能不存在)下面是一个更健壮的Python脚本示例,它读取电压,并在电压异常时通过系统日志(syslog)记录警告,你也可以集成邮件、HTTP API等告警方式。
#!/usr/bin/env python3 import subprocess import syslog import time from datetime import datetime # 配置参数 UPS_NAME = "santak@localhost" VOLTAGE_NOMINAL = 220.0 # 标称电压 VOLTAGE_LOW_THRESHOLD = 200.0 # 低压告警阈值 (V) VOLTAGE_HIGH_THRESHOLD = 250.0 # 高压告警阈值 (V) CHECK_INTERVAL = 30 # 检查间隔,单位秒 def get_ups_variable(var_name): """使用upsc命令获取指定UPS变量的值""" try: cmd = ["upsc", UPS_NAME, var_name] result = subprocess.run(cmd, capture_output=True, text=True, timeout=5) if result.returncode == 0: return result.stdout.strip() else: syslog.syslog(syslog.LOG_ERR, f"Failed to run upsc: {result.stderr}") return None except subprocess.TimeoutExpired: syslog.syslog(syslog.LOG_ERR, "upsc command timed out") return None except FileNotFoundError: syslog.syslog(syslog.LOG_ERR, "upsc command not found. Is NUT installed?") return None except Exception as e: syslog.syslog(syslog.LOG_ERR, f"Unexpected error reading UPS: {e}") return None def monitor_voltage(): syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_DAEMON) syslog.syslog(syslog.LOG_INFO, "UPS voltage monitor started.") while True: voltage_str = get_ups_variable("input.voltage") status_str = get_ups_variable("ups.status") if voltage_str: try: voltage = float(voltage_str) timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') log_msg = f"[{timestamp}] UPS Status: {status_str}, Input Voltage: {voltage:.1f}V" # 判断状态并记录 if status_str == "OB": syslog.syslog(syslog.LOG_WARNING, log_msg + " - ON BATTERY!") elif voltage < VOLTAGE_LOW_THRESHOLD or voltage > VOLTAGE_HIGH_THRESHOLD: syslog.syslog(syslog.LOG_WARNING, log_msg + f" - Voltage out of range! (Nominal: {VOLTAGE_NOMINAL}V)") else: syslog.syslog(syslog.LOG_INFO, log_msg) # 你也可以在这里添加其他动作,比如写入数据库、调用Webhook等 # if voltage > 240.0: # send_alert_email("High Voltage Alert", f"Voltage is {voltage}V") except ValueError: syslog.syslog(syslog.LOG_ERR, f"Could not parse voltage value: '{voltage_str}'") else: syslog.syslog(syslog.LOG_ERR, "Could not retrieve input voltage.") time.sleep(CHECK_INTERVAL) if __name__ == "__main__": monitor_voltage()将脚本保存为/usr/local/bin/ups_voltage_monitor.py,并添加执行权限。你可以使用systemd将其作为一个后台服务运行,这样更可靠。
4.3 创建 Systemd 服务进行后台监控
创建一个systemd服务文件/etc/systemd/system/ups-voltage-monitor.service:
[Unit] Description=UPS Input Voltage Monitor After=nut-server.service network.target Wants=nut-server.service Requires=nut-driver.service [Service] Type=simple User=root ExecStart=/usr/bin/python3 /usr/local/bin/ups_voltage_monitor.py Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target然后启用并启动这个服务:
sudo systemctl daemon-reload sudo systemctl enable ups-voltage-monitor.service sudo systemctl start ups-voltage-monitor.service sudo systemctl status ups-voltage-monitor.service现在,你的电压监控脚本就会在后台持续运行,并将日志输出到系统日志(journalctl)。你可以通过sudo journalctl -u ups-voltage-monitor -f来实时跟踪。
5. 常见问题与排查技巧实录
在实际部署中,你几乎一定会遇到一些问题。以下是我踩过的一些坑和解决方法。
5.1 UPS驱动无法启动或连接失败
问题现象:sudo systemctl status nut-driver显示失败,/var/log/syslog中有Driver failed to start或Cannot open UPS device的错误。
排查步骤:
- 确认USB连接与识别:再次执行
lsusb,确认UPS设备出现。拔插USB线,观察dmesg | tail的输出,看是否有新的USB设备接入记录。 - 检查驱动匹配:运行
sudo nut-scanner -U。这会列出所有检测到的USB设备及其推荐的NUT驱动。对比你ups.conf中配置的driver参数。有时UPS型号比较新或冷门,可能需要尝试不同的驱动,比如blazer_usb或genericups。 - 检查权限问题:这是最常见的原因。确保你已按照前文步骤设置了UDEV规则,并且
/dev/hidrawX或/dev/usb/hiddevX的设备文件权限为crw-rw----,且所属组为nut。重启nut-driver服务前,可以手动运行sudo chmod 660 /dev/hidraw0 && sudo chown root:nut /dev/hidraw0进行测试。 - 尝试指定端口:在
ups.conf中,将port = auto改为具体的设备路径,例如port = /dev/hidraw0。nut-scanner的输出通常会给出建议的端口。 - 查看详细驱动日志:可以手动以调试模式启动驱动来获取更多信息(先停止
nut-driver服务):
注意看输出的错误信息。sudo upsdrvctl -D -u nut start
5.2 upsc 命令连接被拒绝 (Connection refused)
问题现象:运行upsc santak@localhost返回Error: Connection failure: Connection refused。
排查步骤:
- 确认 upsd 服务正在运行:
sudo systemctl status upsd。 - 确认 upsd 正在监听端口:
sudo netstat -tlnp | grep 3493。应该看到upsd进程正在监听127.0.0.1:3493或:::3493。 - 检查认证信息:确保
upsc命令使用的UPS名称(santak)与ups.conf中定义的[santak]完全一致(包括大小写)。如果是远程连接,格式应为upsname@hostname。 - 检查防火墙:虽然我们配置为监听本地,但如果误配了防火墙阻止了3493端口,也会导致问题。对于本地连接,防火墙通常不是问题。
5.3 能连接但读取不到 input.voltage 变量
问题现象:upsc santak@localhost能连接,但输出的变量列表里没有input.voltage,或者其值为空。
排查步骤:
- 列出所有变量:运行
upsc santak@localhost查看完整列表。有些UPS厂商的变量命名可能略有不同,比如可能是input.voltage.input或UPS.input.voltage。NUT驱动会尽量标准化,但可以查看原始变量名。 - 检查驱动支持度:并非所有UPS都通过USB HID协议报告输入电压。有些低端UPS可能只报告基本状态(在线/电池)。你可以尝试查询
ups.status和battery.charge来确认驱动基本工作正常。 - 尝试其他通用变量:
input.voltage是标准变量名。如果确实没有,可能你的UPS不支持报告此数据。可以查阅UPS的说明书或联系厂商确认。 - 升级NUT驱动:较旧版本的NUT驱动可能对新设备支持不全。考虑从NUT官方源码编译更新版本的驱动(对于Jetson平台需要交叉编译或本地编译,有一定复杂度)。
5.4 UPS状态切换时,系统未按预期关机
问题现象:拔掉UPS市电输入,UPS状态变为OB(On Battery),但upsmon没有触发关机。
排查步骤:
- 确认 upsmon 配置:检查
/etc/nut/upsmon.conf中的MONITOR行,确保用户名密码正确,且末尾有master关键字。 - 检查 upsmon 服务状态:
sudo systemctl status nut-monitor。 - 查看 upsmon 日志:
sudo tail -f /var/log/syslog | grep upsmon。当UPS状态改变时,upsmon会记录日志。关注是否有UPS santak@localhost is on battery和Executing automatic power-fail shutdown这样的信息。 - 确认关机延迟参数:
upsmon.conf中有MINSUPPLIES 1(最少需要1个电源供应)和DEADTIME 15(进入电池状态后,等待多少秒才认为电源故障)等参数。确保DEADTIME不是设得过大。 - 手动测试关机命令:以root身份执行
sudo /sbin/shutdown -h now,看系统是否能正常关机。如果不能,可能是shutdown命令的路径问题。在upsmon.conf中,使用which shutdown得到的绝对路径。
5.5 在 Docker 容器中访问 NUT
进阶场景:如果你的应用运行在Docker容器中,需要从容器内读取宿主机的UPS状态。
解决方案:
- 修改 upsd 监听地址:在宿主机的
/etc/nut/upsd.conf中,添加LISTEN 0.0.0.0 3493,让upsd监听所有网络接口。 - 配置容器网络:在运行容器时,使用
--network host模式,这样容器可以直接使用宿主机的网络栈,访问localhost:3493。这是最简单的方式。 - 或者映射端口:如果不用host网络,可以在运行容器时添加端口映射
-p 3493:3493,并在容器内连接宿主机的IP地址,而不是localhost。 - 容器内安装 nut-client:在容器镜像中安装
nut-client包,以便使用upsc命令。 - 注意安全性:向网络开放
upsd端口存在安全风险。务必在upsd.users中设置强密码,并考虑使用防火墙限制访问IP。更好的做法是,在宿主机上运行一个简单的HTTP API代理(例如用Python Flask编写),容器通过HTTP来查询UPS状态,而不是直接暴露NUT端口。
通过以上步骤,你应该能够在reComputer r1000上成功搭建一套稳定可靠的UPS监控系统,不仅能读取输入电压,还能实现断电自动关机、电压异常告警等高级功能,为你边缘计算应用的稳定运行增添一份坚实的保障。这套方案的核心——NUT,其强大之处在于它的通用性和可编程性,一旦打通,你可以根据业务需求,轻松扩展出更多的自动化运维场景。