Skip to content

Windwos下启用WOL功能

约 5901 字大约 20 分钟

WindowsWOL

2025-05-10

前言

Wake-on-LAN(WOL, 网络唤醒)是一种以太网或令牌环计算机标准,允许通过网络消息开启或唤醒睡眠模式的计算机。该消息通常由连接到同一局域网 (LAN) 的设备上运行的程序发送到目标计算机。也可以通过使用子网定向广播或 WoL 网关服务从另一个网络发起消息。它基于 AMD 的 Magic Packet 技术 ,该技术由 AMD 和惠普共同开发,并于 1995 年被提议作为标准。

简而言之,就是能在局域网下通过发送魔术包的方式唤醒计算机。这有什么好处呢?

试想一个场景,你的家里有一台配置比较高的电脑或服务器,安装一些开发环境,启动了一些服务:Nginx、Redis、Mysql、Kafka 等等。由于配置高又运行这么些服务,功耗也同样高,所以我们必然不会全天候运行,所以想过弄一个低功耗的小主机/小型服务器,7x24 小时不间断运行。 我考虑过迷你主机、Nas主机,但它们被设计的使用场景都不符合我的需求。看过不少品牌的迷你主机,它的性能通常比Nas高,但又不如我们的标准主机,而且它的扩展性也不如标准主机,如果运行我们开发所需的服务,它的功耗一样不会低,那么小的机身还要给它散热,有点太为难它的,那要它做甚?
至于Nas,它的设计目标在于数据存储和共享,通常是 7x24 小时不间断运行,所以要在功耗和性能上做平衡。
说来说去,又回到了问题的起点。那就换一种解决思路,能不能在需要的时候开启,不用的时候关闭呢?当然可以,这就需要用到 WOL 技术了。

1. 设置唤醒

要想开启 Windows 的 WOL 功能有两个部分需要设置:BIOS设置、网卡设置。

1.1 BIOS设置

不同主板进入 BIOS 的方式不同,都可以谷歌得到,这里以我的微星主板为例。
电脑开启时按DEL键进入,在SETTING -> 高级 -> 唤醒事件设置,允许网络唤醒即可。同时还有一项PCIE设备唤醒,字面意思很容易理解,网卡就是一种PCIE设备,所以允许网络唤醒其实也就是允许PCIE设备唤醒,只不过微星把这两个概念拆开了。可能在有的主板上就只有一项PCIE设备唤醒,打开它也是一样的。但PCIE设备并不仅仅只有网卡,其他任何一个开发板只要是有 PCIE 接口可以插在主板上,那么它也可以成为唤醒设备,这其实就是留了一个开放接口的意思,你可以做各种 DIY 实现。这样,我们就可以实现电脑在睡眠/休眠中被唤醒了。

另外,在电源管理设置中有一项ERP/ErP Ready,它默认是打开的,如果想要电脑在关机下也能被唤醒,那就需要关闭它。ErP的意思是与能源有关的产品,它与欧盟对各种电子产品(包括个人电脑)通过的环境法规有关。启用 BIOS 里的 ErP 模式或使用 ErP Ready 设置,将使你的个人电脑在关闭时,可以关闭流向所有组件的电源,将总的电力消耗减少到1瓦或更少。
说人话就是,禁用 ErP 在关机下几乎不耗电池,此时也不允许你用鼠标或键盘唤醒电脑,不能对传入的局域网信号作出反应,也就是说远程网络唤醒功能也因此失效了,那我们自然要禁用它。可能你会担心禁用后会好很多电吗?实际上并不会,禁用 ErP 后也就比启用它在关机下的功能多 1~2W,但这根本无所谓。按照民电 0.68元/度,2W 的设备 7x24 小时不间断运行,一年下来需要 11.91元的电费,相对于你在这一年里的开销来说,这不过于九牛一毛。

1.2 网卡设置

开机进入系统,按下win+R输入ncpa.cpl会打开网络连接,选择你当前使用的那个网卡(插的是网线就选以太网,连的 wifi 就选WLAN),找到属性 -> 配置 -> 电源管理,勾选允许此设备唤醒计算机只允许幻数据包唤醒计算机(可选,但建议开启),并取消勾选允许关闭计算机关闭此设备以节约电源

2. 电源状态

在 ACPI(高级配置与电源接口)规范中,定义了从 S0 到 S5 的一系列电源状态,用于描述操作系统如何控制计算机的电源管理。

状态名称描述
S0工作状态(Working)系统完全运行,所有硬件设备正常供电
S1待机状态(Standby)CPU 停止执行指令,但保持供电,内存保留内容,唤醒非常快
S2深度待机状态(Deeper Sleep)类似 S1,但 CPU 和缓存完全断电;更省电,唤醒稍慢。很少使用
S3睡眠状态(Sleep/Suspend to RAM)内存保持供电,CPU 和外设断电;唤醒速度较快,常见的“睡眠”模式
S4休眠状态(Hibernate/Suspend to Disk)将内存内容保存到硬盘,然后全部断电;唤醒时从磁盘恢复,速度较慢,但更省电
S5关机状态(Soft Off)系统完全关闭,几乎无功耗,但仍可通过特定事件(如唤醒信号)启动

可能之前我们会把睡眠(S3)和休眠(S4)弄混淆,事实上它们的定义标准是不同的。由于 RAM 的读写速度非常高,当我们从睡眠模式下唤醒到进入系统页面,通常只需要 2~3 秒;但硬盘的读写速度远不如 RAM ,即便是一个 SSD 硬盘,从休眠模式下唤醒到进入系统页面,可能也需要 7~8 秒。
在 Windows11 系统中,我们发现只能看到睡眠,其实默认下休眠是被隐藏了,因为 Windows11 系统的关机休眠就比较类似了,一样是把工作内容保存在硬盘,使得开机后可以迅速恢复。

按下win+R输入control打开控制面板,选择电源选项。在左侧的选择电源按钮的功能中可以看到休眠是没有被勾选的,我们可以勾选上,这样在按下Win键并点击关机按钮时就可以看到休眠的选项了。
同时,我们注意的电源选项中还有一项启用快速启动(推荐),它是默认被勾选的,正是由于启用了它,才得以让关机的效果和休眠类似,Windows 刻意隐藏了休眠开关,想用快速启动下的关机来达到休眠效果,也避免了休眠睡眠的含义比较接近,导致用户感觉到歧义。

此时,电脑就设置好了 WOl 唤醒了。可以通过Fing应用(支持Android和IOS)其中的LAN唤醒来验证,IOS 系统亦可下载Awake应用(免费无广,且可集成在快捷指令中)验证。如果有 OpenWrt 的软路由系统,可以安装luci-i18n-wol-zh-cn,将网络唤醒集成在 OpenWrt 中,便于操作。

至此,就已经设置好了主机网络唤醒。

3.设置休眠

上面说的都是把主机从睡眠/休眠/关机状态下唤醒,那么我们还想要在主机醒着的状态下进入到睡眠/休眠/关机状态如何做呢?这里当然不是要说在电脑上通过点击来操作,这样没有意思,我们需要通过指令的方式让主机进入到睡眠/休眠/关机状态。

通过命令行(cmd)窗口执行shutdown --help可以看到指令支持的操作如下:

这里关注几个我们需要的:

指令效果
shutown /s关机
shutown /h休眠
shutown /r重启

但是,我们没有看到睡眠的指令。经过一番搜索,找到两条指令可以实现睡眠或休眠的效果:rundll32.exe powrprof.dll,SetSuspendState 0,1,0rundll32.exe powrprof.dll,SetSuspendState Sleep。这两种指令经过验证效果是一样的。
为什么说是实现睡眠或休眠的效果呢?即睡眠休眠只能二选一,那什么时候是睡眠,什么时候是休眠呢?

默认情况下,休眠功能是启用的,那么上面的指令效果就是休眠,则它等价于shutown /h。可以通过powercfg -h off(powershell 管理员权限)来关闭休眠功能,此时shutdown /h指令会失效,同时在电源选项中亦不存在休眠启用快速启动(推荐)的设置,而指令的效果也就变成睡眠了。所以,需要斟酌一下,到底要不要关闭休眠功能。如果关闭休眠后想再次打开,可执行powercfg -h on
如何分辨是从睡眠中醒来,还是从休眠中醒来?查看主机唤醒时,显示器有没有显示主板BIOS的图案,如果有就说明是从休眠中醒来,否则不是。

4. 进阶操作

如何便捷地通过 iPhone 在局域网下唤醒/休眠主机?这里我总结了一套实践经验。
因为 IOS 的快捷指令中支持 SSH 连接并发送指令,那么完全可以通过 SSH 连接到 OpenWrt/Windows 来实现唤醒/休眠主机,但是考虑到操作统一性和便捷性,我实际的做法是:

4.1 Windows 部分

触发脚本

然而在实操踩坑中发现,对于shutdown /s(关机)和shutdown /r(重启)的指令响应逻辑没问题,但是睡眠休眠就有问题了,直接执行相关命令会导致,主机刚进入睡眠休眠状态又立即被唤醒了。
因此我在 Windows 用户目录下放了两个bat脚本,定义了临时触发器来执行操作,供 OpenWrt 通过 SSH 调用,具体如下。

trigger_sleep.bat
@echo off
setlocal

:: 获取当前时间 + 1 分钟
for /f "tokens=1,2 delims=:" %%a in ("%time%") do (
    set /a hh=1%%a %% 100
    set /a mm=1%%b + 1
)
if %mm% GEQ 60 (
    set /a mm=0
    set /a hh+=1
)
if %hh% GEQ 24 set /a hh=0

:: 格式化为 HH:MM(确保补零)
set hh=0%hh%
set mm=0%mm%
set hh=%hh:~-2%
set mm=%mm:~-2%

:: 创建一次性计划任务,执行“睡眠”
schtasks /create /tn "TriggerSleep" /tr "rundll32.exe powrprof.dll,SetSuspendState 0,1,0" /sc once /st %hh%:%mm% /f >nul
schtasks /run /tn "TriggerSleep" >nul

echo Will sleep at %hh%:%mm%
endlocal

这两个脚本,trigger_sleep.bat是用来触发睡眠指令,trigger_hibernate.bat是用来触发休眠指令。

开启SSH

如果想通过 SSH 来管理 Windows 系统,就需要安装OpenSSH服务,Windows11 默认已经安装了 SSH 的客户端,此时我们安装服务端。
有两种方式安装:

方式一:
进入设置->系统->可选功能->添加可选功能,搜索OpenSSH 服务器安装

方式二:

# 安装
Add-WindowsFeature -Name OpenSSH-Client, OpenSSH-Server
# 安装完成后就自动运行了
# 查看
Get-Service -Name sshd
# 连接测试
ssh localhost

设置为开机自启:按WIN键搜索计算机管理,然后打开服务找到OpenSSH SSH Server,修改属性将启动类型调整为自动(延迟启动)

SSH密钥登录

可以借助Git bash生成密钥,执行ssh-keygen -t rsa -f ~/.ssh/id_rsa(生成RSA密钥)或ssh-keygen -t ed25519 -f ~/.ssh/id_rsa(生成ed25519密钥),前者广泛兼容,后者安全性更高,随便选择一种即可。
然后把生成的密钥对中的公钥内容复制到 Windwos 用户目录下的.ssh\authorized_keys文件中,如果文件不存在可自行创建,注意文件没有后缀。示例:

authorized_keys
  ssh-rsa AAAAB4NzaC1yc2EAAAADAQABAAABAQCC8P8z96xo2EcfejdrvEt/6Tc2qhX7FhLevcqjhNvQYPYmQaMwZElsi0QAABAQCC9P8z96xo1EcfejdrvdrvEt/9Tc2q root@ImmortalWrt

接着就是 Windows 的特有操作,更改authorized_keys文件权限,否则无法通过密钥登录。以下命令二选一即可:

  # 远程通过 ACL 更改权限
  ssh --% mayee@192.168.0.88 icacls.exe "C:\Users\mayee\.ssh\authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F" /grant "mayee:F"
  # 服务端修改权限
  icacls.exe "C:\Users\mayee\.ssh\authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F" /grant "maye:F"

注意:这个操作是授权,表示AdministratorsSYSTEMmayee将有完全控制权限,一定要把自己的用户名加上,否则之后无法修改此文件。如果忘了加可以用此命令补icacls "C:\Users\mayee\.ssh\authorized_keys" /grant "mayee:F"

在 Windows OpenSSH 中,默认的授权密钥存放位置为ProgramData\ssh\administrators_authorized_keys,此位置对应为管理用户权限。因此需要修改默认授权文件位置。通过文本编辑器(如 VSCode)打开ProgramData\ssh\sshd_config,修改以下条目(需要管理员权限,也可以把文件复制出去,改完后再覆盖回来):

sshd_config
  #允许公钥授权访问,确保条目不被注释
  PubkeyAuthentication yes

  #授权文件存放位置,确保条目不被注释
  AuthorizedKeysFile .ssh/authorized_keys

  #可选,关闭密码登录,提高安全性
  PasswordAuthentication no

  #注释掉默认授权文件位置,确保以下条目被注释
  #Match Group administrators
  #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

  # 注意,OpenSSH 8.8 及以上版本中,默认禁用了使用 SHA-1 哈希算法的 RSA 签名,如果你用的 RSA 密钥就需要加这两行,ed25519 密钥则不需要加
  HostKeyAlgorithms +ssh-rsa
  PubkeyAcceptedAlgorithms +ssh-rsa

重启 OpenSSH 服务:在 PowerShell 中执行Restart-Service sshd(管理员权限)。
相关指令:

  Get-Service sshd  # 查看状态
  Stop-Service sshd # 关闭服务
  Restart-Service sshd # 重启服务

4.2 OpenWrt 部分

前文提到可以安装luci-i18n-wol-zh-cn,它是一个可视化的操作页面,功能实现依赖的是etherwake,也就是说只安装etherwake用命令行的方式操作就可以了,那样连 OpenWrt 后台页面都不用进。

可以在 OpenWrt 后台页面软件包中安装etherwake,或者执行命令opkg install etherwake

在 OpenWrt 中,LuCI(Lua Configuration Interface) 是其默认的 Web 界面管理系统,LuCI 本质是 一套用 Lua 编写的 Web 应用逻辑,是一种让 Web 服务器运行外部程序(通常是脚本)的标准接口协议,用来处理动态网页请求。但它并不自带服务器功能,它必须运行在一个 Web 服务器之上,而 uHTTPd 是 OpenWrt 默认提供的轻量级 Web 服务器。

文件说明
/etc/config/luciLuCI 的主配置文件,如语言、主题、界面行为等设置
/etc/config/uhttpduHTTPd 的配置文件,控制 Web 服务监听地址、端口、SSL 等
/etc/config/rpcd控制 LuCI 使用的 UBUS RPC 权限(例如哪些用户可以远程读写配置)

cat /etc/config/uhttpd查看配置文件:

uhttpd

可以看到服务器文件都放在/www目录下,cgi 的前缀是cgi-bin。因此,为了便捷我我们在/www/cgi-bin目录下新增一个文件wol

wol

然后可以通过http://192.168.0.88/cgi-bin/wol/<cmd>访问。cmd 可选值:

  • ping:检测主机是否在线
  • sleep:睡眠
  • hibernate:休眠
  • wake:唤醒
  • shutdown:关机
  • reboot:重启

4.3 IOS 部分

IOS 快捷指令请求 OpenWrt 脚本的逻辑流程如下:

结语

上述这套打法可以轻松实现在局域网内,用 iPhone 手机管理主机。可能你会说只能在局域网中使用还是有点鸡肋啊,能不能不在局域网也可以管理主机呢?当然可以,这也是我们下一篇文章的主题:Lucky内网穿透实践