windows 做 NAS 的 UPS 断电自动关机方案
前言
一直以来,我都喜欢用家用电脑来做NAS存储,一个是便宜,另一个是可扩展性高,可以搞到 ATX 全塔 12 盘位的方案,非常的爽。系统方面使用 windows 宿主机 + linux 虚拟机 。由于家里供电不如机房那么稳定,所以前后也用了好几年的 UPS 的防断电方案。接下来就总结一下,在 windows 下 如何让 UPS 在断电的时候,主动关机。
方案 1 ping 内网设备判断是否断电 BAT 脚本实现
- 来源: https://gist.github.com/chenshaoju/ebbf7542ffaa8afc776a90f50959cf35
- 计划任务设置: https://twitter.com/chenshaoju/status/973109556640333825
@echo off
REM 注意:此脚本需要在执行的计算机具备UPS为前提的条件下进行,且目标IP设备不能具有UPS。
REM 此批处理可以检测目标IP是否因为停电而失效,一旦失效则在180秒后关机。
REM 需将此批处理写入计划任务才能使用,建议每隔60秒执行一次。
REM 若不知道如何配置计划任务,请参阅 https://twitter.com/chenshaoju/status/973109556640333825
REM 若参照60秒执行一次的话,在120至180秒内若恢复供电(能Ping通),则会取消关机。
REM 若路由器或需要检测的目标IP不是 192.168.1.1 ,请手动修改下方的 192.168.1.1 IP地址。
REM 关机等待时间不建议设置太短,避免手动开机但目标IP未启动时又立刻自动关机。
REM 若只需要监控一个设备(默认),请勿注释下一行。
ping /n 3 /l 1 192.168.1.1|findstr "TTL=" && ( goto PowerOn ) || goto PowerOff
REM 若需要监控两个(或多个,请自行参考格式添加)设备(可选),请取消注释下一行(删除开头的 "REM " ),并注释或删除上一行,此行是“和”(AND)的逻辑情况,只有两个IP都失效的情况下才会执行关机。
REM ping /n 3 /l 1 192.168.1.1|findstr "TTL=" && ( goto PowerOn ) || ping /n 3 /l 1 192.168.1.2|findstr "TTL=" && ( goto PowerOn ) || goto PowerOff
:PowerOn
shutdown /a
exit 0
:PowerOff
shutdown /s /t 180
exit 0
说明: 这个方案的好处是不用引入第三方软件,系统内置的脚本就可以实现。缺点是需要有个其他的内网设备,例如路由器,假如路由器也有 UPS 那就没用了。
方案 2 两次失败后才会待机 .net方案
- 来源:https://github.com/huxim/UPS_Hibernate
- 下载:https://github.com/huxim/UPS_Hibernate/releases
说明: 这个方案的好处是可以确认两次 ping 失败 , 避免路由器一重启,把 NAS 给关了的尴尬。缺点就是依赖.net。
方案3 支持 USB 管理的 UPS 根据电量百分比来关机
这是个我自己原创的程序 使用 aardio 编译
import console;
import fsys.table;
console.setTitle("UPS检测状态");
var config = fsys.table("/config")
config.load();
if(config.percent == null){
config.percent = 90;
config.debug = 0;
config.shutdownTime = 300;
}else{
config.percent = tonumber(config.percent);
config.shutdownTime = tonumber(config.shutdownTime);
}
config.save();
class SYSTEM_POWER_STATUS {
BYTE ACLineStatus;
BYTE BatteryFlag;
BYTE BatteryLifePercent;
BYTE Reserved1;
int BatteryLifeTime; // 这里需要是有符号的32位整型,自动转换工具会自动使用无符号的 要注意
int BatteryFullLifeTime; //同上
}
//https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/ns-winbase-system_power_status
var 电源信息 = ::SYSTEM_POWER_STATUS();
var t = 0;
while(1){
::Kernel32.GetSystemPowerStatus(电源信息);
if(config.debug == 1){
console.dump(电源信息);
}
if(
电源信息.ACLineStatus === 0 &&
电源信息.BatteryLifePercent <= config.percent &&
t === 0
){
execute("shutdown /s /t "++ config.shutdownTime);
t = 1;
}
if(电源信息.ACLineStatus === 1 && t === 1){
execute("shutdown /a");
t = 0;
}
sleep(5000);
}
说明:每隔 5 秒检测一次,如果是交流电状态,就继续循环,如果是直流电,且百分比小于设定值,就开始准备关机,期间如果供电恢复,就取消关机。第一次运行程序后,会生成配置文件,可配置 电量百分比,关机时间,是否打印系统 API 返回的数据(用于调试)。
PS
我一般喜欢开机自动登录,然后再锁屏。
锁屏代码
C:\Windows\System32\rundll32.exe user32.dll LockWorkStation
自动登录
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
"DefaultUserName"="用户名"
"AutoAdminLogon"="1"
"DefaultPassword"="密码"