UPS断电守护:从电源管理到远程唤醒的实战笔记

UPS断电守护:从电源管理到远程唤醒的实战笔记(转)

原文地址: https://baijiahao.baidu.com/s?id=1858228971535438048

引子:一块硬盘引发的“断电焦虑”

家里的机械硬盘已经换了一轮企业级大容量盘,专门存放不可再生的重要数据。最怕的却是深夜突然跳闸,电流一断,硬盘磁头“哐当”一声,所有备份瞬间归零。隔壁电工隔三差五拉闸验表,无奈之下入手一台山特 SANTAK TG-BOX 850 UPS,标称510W,先保命再谈扩容。

设备初印象:小身材,大插座

右下角那台方方正正的“插座”就是主角,机身比笔记本大不了多少,却要扛起100W+的整机负载——生产力主机、软路由、酷播云存储、斐讯K3 网关统统插在上面。510W 功率账面数字看似保守,实测市电掉电瞬间能稳住 10 分钟,足够让系统优雅关机。

从“单点唤醒”到“统一调度”:升级动机

原方案是用 Linux 自带的 nut 驱动管理 UPS,再配合 etherwake 做网络唤醒。思路简单却留有两个隐患:

* 定时任务与 UPS 监控分离,断电触发关机指令可能落在“唤醒指令”之后,导致机器已关机,UPS 电量耗尽,数据还是丢了;
* 来电后电池没充满就擅自开机,UPS 仍在“安全期”却误判“低电量”,第二天清晨发现服务器集体宕机在启动画面。

干脆把“监控—判断—关机—唤醒”做成一条流水线,让 UPS 当裁判,也让 UPS 当发令枪。

设计思路:一条电量阈值线,管住所有机器

设定 60% 剩余电量 为“红线”。

* 红线以下:立刻按优先级远程关机,先关远程节点,再关本地节点;
* 红线以上:进入“唤醒窗口”,早起的豆子机 8:00 醒,安静的服务器 6:00 醒;
* 来电后若电池未充满阀值,再补一次唤醒任务,确保设备自动上线不卡壳;
* 每次断电前给管理员发一封告警邮件,留痕+心理安慰双保险。

环境准备:三行命令搭好 nut 基站

apt update && apt install nut -y # 装驱动
echo 'maxretry = 3' >> /etc/nut/ups.conf # 重试次数
[tgbox850] # 配置节点
driver=usbhid-ups
port=auto
desc="SANTAK TGBOX-850 UPS"

修改 nut.conf 的 MODE=standalone,重启服务:

systemctl start nut-driver nut-server
systemctl enable nut-driver nut-server

命令行输入 upsc tgbox850 能看到电池百分比即算配置成功。

网络唤醒:用 Python 把魔术包扔出去

安装 etherwake:

apt update && apt install etherwake -y

写一个 Flask 小应用 在远程目标机上跑:

from flask import Flask, jsonify, request

import os

app = Flask(__name__)

@app.route('/shutdown', methods=['GET'])
def shutdown(): return jsonify({'error': False, 'msg': 'ok'}), 200

@app.route('/reboot', methods=['GET'])
def reboot(): os.system('reboot'); return jsonify({'error': False, 'msg': 'ok'})

if __name__ == '__main__': app.run(debug=False, host='0.0.0.0', port=5000)

把以上代码存成 reboot.py,再写一个 systemd 服务文件 evling-reboot.service,开机自启即可。

电源管家:把唤醒、关机、告警做成循环任务

主脚本 power_manager.py 负责:

* 每分钟读取 UPS 电量;
* 按 Mac 地址列表唤醒指定服务器;
* 来电后补发一次唤醒;
* 电量低于阀值前发送邮件。

关键片段示例:

import requests, datetime, time

self.shutdown_urls = ['http://pve-prod.evling.tech/shutdown5000', 'http://pve-nas.evling.tech/shutdown5000'] # 远程 API 地址清单
self.str_charge_cmd = '/sbin/shutdown -h now' # 关机命令模板
self.etherwake_tpl = '/usr/sbin/etherwake -i {}' # 网络唤醒命令模板
self.interfaces = ['vmbr0', 'vmbr10', 'vmbr11', 'vmbr12', 'vmbr8', 'vmbr9'] # 所有可用网口备用唤醒接口
self.wake_list = [
    {'name': 'pve-prod', 'str_datetime_begin': '06:00', 'str_datetime_end': '23:00', 'mac': '70:xx:xx:e5'}, 
    {'name': 'pve-nas', 'str_datetime_begin': '08:00', 'str_datetime_end': '23:00', 'mac': '70:xx:xx:39'}
] # 设备名称+唤醒区间+MAC

for wake_item in self.wake_list: 
    if datetime.now() >= datetime.strptime(f"{wake_item['str_datetime_begin']} {wake_item['str_datetime_end']}", "%H:%M") and power_manager.charge != None and power_manager.charge <= power_manager.shutdown_charge: 
        for downing_item in downing_list: 
            if downing_item > power_manager.charge: 
                shutdown_flag = True break time.sleep(1) # 若电量继续下降,则执行远程关机 
            if shutdown_flag: 
                for url in self.shutdown_urls: 
                    requests.get(url) print(f"Sent shutdown to {url}") # 来电后补发一次唤醒脚本可放在开机自启服务里循环调用 

同样把脚本存为 systemd 服务 evling-powermanagement,重启间隔设为每 60 秒一次,避免启动风暴限制。系统默认的 StartLimitInterval=2s 要记得调高。开机自启:systemctl enable evling-powermanagement。至此,整套“断电守护+远程唤醒”闭环完成。

posted @ 2026-03-02 09:59  汉学  阅读(0)  评论(0)    收藏  举报