Mac睡眠模式优化:蓝牙Wi-Fi自动控制脚本

Mac睡眠模式优化:蓝牙Wi-Fi自动控制脚本

1. 为什么需要优化Mac的睡眠功耗?

作为一名长期使用MacBook Pro的开发者,我经常遇到这样的困扰:明明电脑已经合盖进入睡眠状态,第二天打开却发现电量消耗了10%-15%。经过多次测试排查,发现问题出在蓝牙和Wi-Fi模块上——即使进入睡眠状态,这些无线模块仍在持续耗电。

Mac的默认睡眠模式(称为"标准睡眠")会保持网络连接和蓝牙功能,以便实现以下功能:

  • 接收iCloud同步和通知
  • 允许Find My Mac定位
  • 支持Apple Watch解锁
  • 保持AirDrop和Handoff的可用性

但对于不需要这些功能的场景,这种设计会导致不必要的电量消耗。特别是:

  • 蓝牙4.0以上的模块待机功耗约1-5mA
  • Wi-Fi模块在睡眠状态下的扫描功耗约3-10mA
  • 两者叠加可能导致每小时消耗0.5%-1%的电量

2. 手动控制无线模块的局限性

在系统设置中直接关闭蓝牙和Wi-Fi确实能省电,但存在三个明显问题:

2.1 操作繁琐

每次睡眠前需要:

  1. 点击菜单栏蓝牙图标 → 关闭蓝牙
  2. 点击菜单栏Wi-Fi图标 → 关闭Wi-Fi 唤醒后又要重复开启操作,一天多次操作极其麻烦

2.2 功能中断

手动关闭会导致:

  • AirPods等蓝牙设备无法自动连接
  • 网络依赖的服务(如邮件推送)全部中断
  • 需要使用时必须手动重新开启

2.3 状态不同步

实测发现:

  • 合盖睡眠时如果Wi-Fi开着,唤醒后可能显示已连接但实际无网络
  • 蓝牙设备经常需要重新配对
  • 菜单栏图标状态与实际功能不一致

3. 自动化解决方案:睡眠控制脚本

通过shell脚本+launchd实现自动化控制是最稳定的方案。以下是具体实现步骤:

3.1 创建控制脚本

在~/Library/Scripts/目录下新建sleep_wifi_bluetooth.sh:

#!/bin/zsh # 获取当前用户 current_user=$(whoami) # 监听睡眠事件 /usr/bin/pmset -g log | grep --line-buffered "Entering Sleep" | while read line do # 关闭蓝牙 blueutil -p 0 # 关闭Wi-Fi networksetup -setairportpower en0 off # 记录日志 echo "[$(date)] Sleep triggered: BT/WiFi OFF" >> /Users/$current_user/Library/Logs/sleep_wifi.log done & # 监听唤醒事件 /usr/bin/pmset -g log | grep --line-buffered "Wake from Sleep" | while read line do # 延迟5秒确保系统完全唤醒 sleep 5 # 开启蓝牙 blueutil -p 1 # 开启Wi-Fi networksetup -setairportpower en0 on # 记录日志 echo "[$(date)] Wake triggered: BT/WiFi ON" >> /Users/$current_user/Library/Logs/sleep_wifi.log done

3.2 安装依赖工具

需要先通过Homebrew安装blueutil:

brew install blueutil

3.3 创建LaunchAgent

在~/Library/LaunchAgents/下创建com.user.sleepwifi.plist:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.user.sleepwifi</string> <key>ProgramArguments</key> <array> <string>/bin/zsh</string> <string>/Users/YOUR_USERNAME/Library/Scripts/sleep_wifi_bluetooth.sh</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/Users/YOUR_USERNAME/Library/Logs/sleep_wifi.out</string> <key>StandardErrorPath</key> <string>/Users/YOUR_USERNAME/Library/Logs/sleep_wifi.err</string> </dict> </plist>

3.4 加载并启动服务

launchctl load ~/Library/LaunchAgents/com.user.sleepwifi.plist launchctl start com.user.sleepwifi

4. 方案优化与进阶配置

4.1 条件性禁用

可以通过修改脚本实现智能判断:

# 只在电池模式下启用节能 current_power=$(pmset -g batt | grep -o "AC Power\|Battery Power") if [ "$current_power" = "Battery Power" ]; then # 执行关闭操作 fi

4.2 白名单功能

保留特定蓝牙设备的连接:

# 保持Magic Mouse连接 blueutil --connect 40-ED-98-A1-B2-C3

4.3 网络例外处理

确保唤醒后自动连接常用Wi-Fi:

networksetup -setairportnetwork en0 "Your_WiFi_SSID" "password"

5. 实测效果对比

经过一周的测试(M1 MacBook Pro 13" 2020):

场景8小时睡眠耗电年省电量估算
默认设置8%-12%-
手动关闭无线2%-3%约30次完整充电
本自动化方案1%-2%约40次完整充电
飞行模式+蓝牙关闭0.5%-1%约50次完整充电

注意事项:在macOS Ventura及更新版本中,可能需要额外授予Terminal完全磁盘访问权限,否则networksetup命令可能无法执行。

6. 常见问题排查

6.1 服务未自动启动

检查日志:

cat ~/Library/Logs/sleep_wifi.err

常见解决方法:

  1. 确保脚本有执行权限:chmod +x ~/Library/Scripts/sleep_wifi_bluetooth.sh
  2. 检查plist文件中的用户名路径是否正确
  3. 重启launchd服务:launchctl unload ~/Library/LaunchAgents/com.user.sleepwifi.plist然后重新load

6.2 Wi-Fi无法正常关闭

可能是网络接口名称不同:

networksetup -listallhardwareports

将脚本中的en0替换为实际的Airport接口名

6.3 蓝牙设备连接异常

建议:

  1. 在脚本中添加2秒延迟后再启用蓝牙
  2. 对于Magic Keyboard等设备,可能需要先断开再连接:
blueutil --disconnect 40-ED-98-A1-B2-C3 sleep 1 blueutil --connect 40-ED-98-A1-B2-C3

7. 替代方案对比

7.1 第三方工具

  • Amphetamine:提供更精细的控制,但需要保持常驻
  • SleepControl:商业软件,功能全面但年费制
  • BlueHarvest:专注蓝牙管理,缺少Wi-Fi控制

7.2 系统自带方案

  • 低电量模式:会降低性能,且不彻底关闭无线模块
  • 节能模式:仅影响显示器和硬盘休眠时间

7.3 终端命令方案

直接使用pmset:

# 深度睡眠模式(会断开所有网络) sudo pmset -a hibernatemode 25

但会导致唤醒速度明显变慢(约5-8秒)

经过三个月的实际使用,这个自动化方案使我的MacBook Pro在睡眠状态下的日均耗电从原来的9.2%降低到了1.8%,特别是在外出时不插电的场景下,电池续航感知明显提升。对于需要保持蓝牙键盘连接的用户,建议在白名单中添加设备地址,并在脚本开头添加5秒延迟,确保系统完全唤醒后再恢复蓝牙连接。