惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

Razeen`s Blog

Let's Encrypt 推出 Gen Y 根证书架构:揭示 Web PKI 的五大未来趋势 通过 Wi-Fi 自动备份你的 iPhone 到 Nas 管理培训感悟:从技术视角看管理之路 从影音中心到 AI 助手:我的50款 Homelab 服务清单 从SSL证书有效期将缩短到47天聊开去 部署一个自己的 Running Page 谈谈特斯拉 Model Y 用车一年的感受和费用分析 弃用 Disqus 评论,使用自建 Waline 使用 Prometheus 和 Grafana 搭建你的证书监控面板 服务器迁移记:一次磁盘换板引发的Linux分区与挂载的学习 改善信息来源, 利用 RSS 高效获取资讯 (RSShub + Reeder5 + WeWe RSS) 多种 Docker 镜像拉取解决方案与实践 App分享 | AppCleaner - Mac上的卸载神器 Azure OpenAI API 申请和使用 如何开通 OneKey 虚拟信用卡,并充值消费 如何拥有一个可长期在国内使用的国外手机号码 分享开通 ChatGPT Plus 过程 如何开通 Depay 虚拟信用卡,并充值消费 如何开通欧易Web3钱包, 交易入账 如何5分钟内1块钱注册 ChatGPT 科学上网 如何注册美区的 Apple ID (2023年/无需科学上网) NAS折腾记(11): NASTool3.0体验和降级 NAS折腾记(10): Docker版本的NASTool配置 NAS折腾记(9): NASTool与微信交互,微信发送消息远程下载电影【多图】 NAS折腾记(8):群晖安装 NASTool 实现影音半自动化【多图】 内网穿透(2):Tailscale 组网实现内网穿透,操作简单,无成本 内网穿透(1):总结了11中内网穿透的方式,总有一种适合你 NAS折腾记(7):从零开始设置(黑)群晖系统 NAS折腾记(6):黑群晖系统安装好后怎么洗白? NAS折腾记(5):群晖硬盘休眠设置与分析 NAS折腾记(4): 20分钟手把手带你完美安装 DS918+ 黑群晖7.1.1 NAS折腾记(3):NAS 装机 NAS折腾记(2):B360-ITX 双M.2 双2.5G网口 6 SATA主版 开箱 NAS折腾记(1):328元的4盘位Nas机箱开箱 Openwrt + Clash 全局科学上网 Newifi3 刷入 OpenWrt 固件 v21.02 利用 Markdown 画一些流程图、时序图、甘特图等 Homelab(8): 搭建自用 Gitlab 与 Docker 仓库 Nginx Tcp 转发保留客户端真实 IP (PROXY Protocol) Homelab (7):IPSec VPN(基于证书认证)客户端设置 Homelab (6): 基于自签发证书的 IPSec VPN 搭建 Homelab (5): DDNS 动态域名解析 Homelab (4): Linux 服务器基础环境准备 Homelab (3): 整体网络与基础硬件介绍 Go学习笔记(十)老项目迁移 go module 大型灾难记录 Github Actions 初体验之自动化部署 Hexo 博客 记一次 Nginx DNS 缓存导致转发问题 Homelab (2): 电信悦me网关修改桥接模式,路由器拨号 Homelab (1):5分钟上手黑群晖 NAS 终极 Bash 脚本指南 Typora 自动上传图片到七牛云 Ubuntu 20.04 LTS 有线网卡驱动安装 折腾 Ubuntu 20.04 LTS 开发环境 Go学习笔记(九) 计时器的生命周期[译] 利用 git hook 规范你的代码与 commit message 规范 git commit message 与自动化版本控制 超详细 vim 配置 (with MacVim) Golang 中的 RESTful API 最佳实践 折腾服务器(开篇) 我的第一台个人服务器 Newifi3 实现低成本家庭级科学上网 Go学习笔记(八) | 使用 os/exec 执行命令 如何用 Go 调用 Windows API Mac OS 自动根据 WI-FI 名字改变网络位置 关于 Docker 清理 MIME Types 速查表 Go学习笔记(七) | 理解OAuth 2.0并实现一个客户端 我又又又把博客迁移了 Go学习笔记(六) | 使用swaggo自动生成Restful API文档 Go学习笔记(五) | 使用代码片段(snippets)提高编码效率 书单 - 2018 IPFS 初体验,利用 IPFS 托管你的静态网站 记一次 PostgreSQL LIKE 索引优化,联合字段 LIKE 查询优化。 Disqus 添加有趣的 Reactions 的功能 TLS 1.3 详解 (RFC 8446解读) gRPC在Go中的使用(三)gRPC实现TLS加密通信与流模式 gRPC在Go中的使用(二)gRPC实现简单通讯 gRPC在Go中的使用(一)Protocol Buffers语法与相关使用 CentOS 安装 tshark 抓包工具 Go学习笔记(四) | win上使用VSCode搭建Go开发环境 日常 Postgres 数据库点滴记录 简单了解 PKCS 规范 美食篇 | DIY戚风蛋糕(烤箱做蛋糕) Go学习笔记(三) | 怎么写Go基准测试(性能测试) TLS1.3正式更新,为Nginx添加TLS1.3的支持 一次诡异的数据库删除 GitHub Pages自定义域名开启HTTPS 证书透明度是什么?它是怎么工作的? Go学习笔记(二) | 我对 recover 的一点误解 搭建证书透明度(certificate-transparency)日志服务之从入门到放弃 修复远程登陆 Centos 时,出现 UTF-8 Warning HTTPS篇之SSL握手过程详解 Go学习笔记(一) | postgres与golang点点滴滴 AWS 命令行界面(aws-cli)从安装到快速上手 数字证书分类及怎么区分各类数字证书 常用 linux 命令小结(一)文件目录操作 云服务器搭建 hexo 博客,git hooks自动更新 SSH 免密登陆, SSH Config 配置 Golang CGO Mac 交叉编译 Windows 使用 goose 让数据库迁移更加轻松
UPS 一拖多:保护你的 NAS 和 Linux 服务器
2025-05-08 · via Razeen`s Blog

最近家里断电了一次,我的群晖因为连接了 UPS 而优雅关机了,但 Linux 服务器由于没有连接 UPS,直接强制断电。这很容易导致数据丢失,严重的硬盘损坏!于是一直没配置的 NUT 今天终于安排上了。 这篇文章就分享一下如何通过 NUT 来实现一台 UPS 同时保护多台设备。

设备情况

  • 群晖 NAS:运行 DSM 7.2

  • Linux 服务器:运行 AlmaLinux 8.1

  • 施耐德 APC UPS:直接连接到群晖上

NUT 是什么?

要实现这个功能,我们需要用到 NUT (Network UPS Tools)。NUT 是一套监控和管理 UPS 设备的开源工具,它允许多台计算机通过网络共享一个 UPS 的状态信息。

其中关键的组成部份如下:

组件功能说明
nut-driver与物理 UPS 通讯
upsd暴露 UPS 状态给网络, upsmon 可以从这个获取状态
upsmon主控模式(primary)可控制关机,从控模式(secondary)只监听
upssched用于延迟关机或超时判断
scripts处理状态变化,如发送通知等

工作原理如下:

flowchart TD
  subgraph Device
    UPS["🔌 UPS (Physical Device)"]
  end

  subgraph Server
    driver["⚙️ nut-driver (upsdrvctl)"]
    upsd["🧠 upsd (NUT Daemon)"]
    upsmon_master["📡 upsmon (Primary)"]
    upssched["⏱️ upssched (Event Scheduler)"]
    notify_master["🔔 notify.sh (on Server)"]
  end

  subgraph Client
    upsmon_slave["🛰️ upsmon (Secondary)"]
    notify_slave["🔔 notify.sh (on Client)"]
  end

  UPS --> driver
  driver --> upsd
  upsd --> upsmon_master
  upsmon_master --> upssched
  upssched --> notify_master
  upsmon_master --> notify_master

  upsd -->|network| upsmon_slave
  upsmon_slave --> notify_slave

在这个设置中,群晖 NAS 将作为主服务器(primary),而 Linux 服务器将作为客户端(secondary)。

当市电断开后,Linux 服务器就能从群晖 NAS 上的 upsd 获取到断电的信息,开始倒计时关机,同时通过脚本通知(这里我配置的是企业微信的通知)。

  1. 登录群晖 DSM 管理界面
  2. 打开「控制面板」>「硬件和电源」>「不断电系统」

image-20250511084234968

  1. 确保已经勾选「启用 UPS 支持」
  2. 在「UPS 类型」选项中选择「USB」(取决于你的 UPS 连接方式)
  3. 设置自定义时间直到电量不足(如果你的UPS电池不靠谱,建议设置个较短的时间)
  4. 勾选上当系统进入待机模式时关闭 UPS , 不然系统只会在断电后进入待机模式,不会主动关机。
  5. 向下滚动到「启用 UPS 网络服务器」选项并勾选
  6. 在「允许的 UPS 设备」下添加你的 Linux 服务器 IP 地址
  7. 点击「应用」保存设置

image-20250511001704684

这样群晖这边就配置好了。

如果你希望电源恢复后自动重启,可以在「控制面板」>「硬件和电源」>「常规」中,勾选修复电源问题后自动重新启动

在 Linux 服务器上安装和配置 NUT

  1. 首先安装 NUT 客户端包:
sudo yum install nut

我当前安装的版本是 2.8.2 (upsd -V 可查看版本)

  1. 编辑 NUT 的主配置文件:
sudo vi /etc/ups/nut.conf

将模式设置为 netclient

MODE=netclient

MODE 可选值如下,可以了解一下。

含义说明
standalone本机使用本地连接的 UPS,所有组件(upsdrv, upsd, upsmon)都在本机运行。用于 单机本地 UPS 管理
netserver本机连接本地 UPS,运行 upsd,允许其他网络客户端通过 NUT 协议连接监控。常用于群晖这类做UPS 主控服务器的场景。
netclient本机不连接 UPS,只通过网络连接远程 UPS 主机(运行 upsd)。本机只运行 upsmon。这是从机最常用的模式。
  1. 编辑监控配置:
sudo vi /etc/ups/upsmon.conf

添加以下行:

MONITOR ups@192.168.1.7 1 monuser secret secondary

MONITOR 的配置格式如下:

MONITOR (“primary”|“secondary”)

参数说明
MONITOR这是固定关键字,表示这一行是 UPS 监视配置。
systemUPS 的名称和主机地址:这里表示远程主机 192.168.1.7 上运行的名为 ups 的 UPS 实例。
powervalue表示这个 UPS 的"电源冗余级别" —— 是我们依赖的几台 UPS 中的一台。如果你有多个 UPS,设置这个数字用于 MINSUPPLIES 的判断(系统至少需要多少电源供应才认为是安全的)。通常设为 1 即可。
username用户名,用于连接远程 upsd 服务。这个用户必须在远程主机的 /etc/nut/upsd.users 中定义,并具有 MONITOR 权限
passwordmonuser 的密码,对应 upsd.users 中配置的密码。
(“primary”/“secondary”)角色类型:secondary 表示这是一个从属客户端,不会主动发起关机,只会等待主控机通知或监听事件自行关机。常见角色是 primary(主控)和 secondary(从属)。

群晖的UPS默认名称就是 ups, 192.168.1.7就是群晖的IP, 默认用户和密码为 monuser ,secret。后面故障排除章节中也会有查看用户名密码的方法。

  1. 测试配置是否正确。

    可以使用DEBUG模式启动运行一下,看看是否能正常工作。

    sudo /usr/sbin/upsmon -D
    

    如果正常,可以看到类似下面输出

    Network UPS Tools upsmon 2.8.2
       0.000000     fopen /run/nut/upsmon.pid: No such file or directory
       0.000026     Could not find PID file to see if previous upsmon instance is already running!
       0.000080     UPS: ups@192.168.1.7 (secondary) (power value 1)
       0.000139     Using power down flag file /etc/killpower
       0.000267     [D1] debug level is '1'
       0.000615     [D1] Saving PID 1141184 into /run/nut/upsmon.pid
       0.001801     [D1] Succeeded to become_user(nut): now UID=57 GID=57
    Init SSL without certificate database
       0.020004     upsnotify: failed to notify about state 2: no notification tech defined, will not spam more about it
       0.020009     [D1] Trying to connect to UPS [ups@192.168.1.7]
       0.021112     [D1] Logged into UPS ups@192.168.1.7
    

    再使用 upsc 指令,查看一下 UPS 状态。

     upsc ups@192.168.1.7
    

    会返回 UPS 的电量,版本等等信息。

    Init SSL without certificate database
    battery.charge: 100
    battery.charge.low: 10
    battery.mfr.date: 2001/01/01
    battery.runtime: 868
    battery.runtime.low: 120
    battery.type: PbAc
    battery.voltage: 13.7
    battery.voltage.nominal: 12.0
    device.mfr: American Power Conversion
    device.model: Back-UPS BK650M2-CH
    device.serial: 9Bxxxxxx
    device.type: ups
    driver.name: usbhid-ups
    driver.parameter.pollfreq: 30
    driver.parameter.pollinterval: 5
    driver.parameter.port: auto
    driver.parameter.synchronous: no
    driver.version: DSM7-2-1
    driver.version.data: APC HID 0.96
    driver.version.internal: 0.41
    input.sensitivity: low
    input.transfer.high: 278
    input.transfer.low: 160
    input.voltage: 224.0
    input.voltage.nominal: 220
    ups.beeper.status: enabled
    ups.delay.shutdown: 20
    ups.firmware: 294803G -292804G
    ups.load: 30
    ups.mfr: American Power Conversion
    ups.mfr.date: 2022/10/25
    ups.model: Back-UPS BK650M2-CH
    ups.productid: 0002
    ups.realpower.nominal: 390
    ups.serial: 9B2xxxxxxx
    ups.status: OL
    ups.test.result: Done and passed
    ups.timer.reboot: 0
    ups.timer.shutdown: -1
    ups.vendorid: 051d
    
  2. 启动并启用 NUT 服务:

sudo systemctl enable nut-monitor
sudo systemctl start nut-monitor

通知到企业微信

最后,我在 Linux 服务器上写了一个脚本,将 UPS 事件通知到企业微信。

  1. 在 Linux 服务器上创建通知脚本:
sudo vi /etc/ups/notify.sh
  1. 添加以下内容(记得替换 YOUR_KEY 为你的企业微信机器人密钥):
#!/bin/bash

WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"

# 获取事件消息
EVENT_MSG="$1"

# 获取当前时间(格式:2025-05-10 18:30:12)
TIMESTAMP=$(date "+%F %T")

# 构造完整推送内容
MSG="[$TIMESTAMP] $EVENT_MSG"

# 发送消息到企业微信
curl -s -X POST "${WEBHOOK_URL}" \
  -H 'Content-Type: application/json' \
  -d "{
        \"msgtype\": \"text\",
        \"text\": {
            \"content\": \"${MSG}\"
        }
      }" >/dev/null 2>&1
  1. 添加执行权限:
sudo chmod +x /etc/ups/notify.sh
  1. 测试脚本
/etc/ups/notify.sh 测试通知

image-20250511081651788

  1. 编辑 upsmon 配置文件:
sudo vi /etc/ups/upsmon.conf

添加 NOTIFYCMD 指令指向你的脚本:

NOTIFYCMD /etc/ups/notify.sh

在 upsmon.conf 中启用你想要通知的事件,例如:

NOTIFYFLAG ONLINE       SYSLOG+EXEC
NOTIFYFLAG ONBATT       SYSLOG+EXEC
NOTIFYFLAG LOWBATT      SYSLOG+EXEC
NOTIFYFLAG FSD          SYSLOG+EXEC
NOTIFYFLAG COMMOK       SYSLOG+EXEC
NOTIFYFLAG COMMBAD      SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN     SYSLOG+EXEC
NOTIFYFLAG REPLBATT     SYSLOG+EXEC
NOTIFYFLAG NOCOMM       SYSLOG+EXEC
NOTIFYFLAG NOPARENT     SYSLOG+EXEC
NOTIFYFLAG CAL          SYSLOG+EXEC
NOTIFYFLAG NOTCAL       SYSLOG+EXEC
NOTIFYFLAG OFF          SYSLOG+EXEC
NOTIFYFLAG NOTOFF       SYSLOG+EXEC
NOTIFYFLAG BYPASS       SYSLOG+EXEC
NOTIFYFLAG NOTBYPASS    SYSLOG+EXEC
  1. 重启 nut-monitor 服务:
sudo systemctl restart nut-monitor

现在,当 UPS 状态发生变化时,比如市电中断或恢复,你将同时在企业微信上收到通知。

断电测试

都配置好后,可以断开 UPS 电源测试一下。

如果此时你打开了群晖WEB,你会发现他会在配置的时间之后,会停止服务,进入安全模式。

image-20250511082134587

随后,Linux服务器会关闭,如果此时你SSH连接着,你会看到

image-20250511082316924

这说明我们配置已经正常工作了。

故障排除

  1. 如何查看日志文件

如果你遇到问题,可以查看以下日志文件:

  • 在 Linux 上:/var/log/messagesjournalctl -u nut-monitor
  • 在群晖上:控制面板 > 日志中心 > 系统日志
  1. 群晖的UPS的配置和密码如何查看。

群晖的UPS配置需要 SSH 到群晖的后台才能看到。

  • /etc/ups/ups.conf :查看UPS的名称和配置,如
[ups]   # << 名称
        driver = usbhid-ups # << 驱动
        port = auto
  • /etc/ups/upsd.users: 查看用户和密码,如
[monuser] # << 用户
                password = secret # << 密码
                upsmon master

你也可以修改这个密码,不过修改完成后需要重启 upsd 服务,使用下面命令重启

synosystemctl restart ups-usb
  1. 如果你的群晖开启了防火墙,记得放行 3493 端口。
  2. 如果你发现你的群晖没有正常关机,只是进入了待机模式,可以参考《市电断电时群晖用UPS实现自动关机的设置》修改一下关机指令。

总结

通过这个设置,我现在可以确保无论何时发生断电,我的群晖 NAS 和 Linux 服务器都能够安全关机,避免数据损坏和文件系统问题~