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。至此,整套“断电守护+远程唤醒”闭环完成。

浙公网安备 33010602011771号