前言

一直以来,我都喜欢用家用电脑来做NAS存储,一个是便宜,另一个是可扩展性高,可以搞到 ATX 全塔 12 盘位的方案,非常的爽。系统方面使用 windows 宿主机 + linux 虚拟机 。由于家里供电不如机房那么稳定,所以前后也用了好几年的 UPS 的防断电方案。接下来就总结一下,在 windows 下 如何让 UPS 在断电的时候,主动关机。

方案 1 ping 内网设备判断是否断电 BAT 脚本实现

@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"="密码"