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 操作繁琐
每次睡眠前需要:
- 点击菜单栏蓝牙图标 → 关闭蓝牙
- 点击菜单栏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 done3.2 安装依赖工具
需要先通过Homebrew安装blueutil:
brew install blueutil3.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.sleepwifi4. 方案优化与进阶配置
4.1 条件性禁用
可以通过修改脚本实现智能判断:
# 只在电池模式下启用节能 current_power=$(pmset -g batt | grep -o "AC Power\|Battery Power") if [ "$current_power" = "Battery Power" ]; then # 执行关闭操作 fi4.2 白名单功能
保留特定蓝牙设备的连接:
# 保持Magic Mouse连接 blueutil --connect 40-ED-98-A1-B2-C34.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常见解决方法:
- 确保脚本有执行权限:
chmod +x ~/Library/Scripts/sleep_wifi_bluetooth.sh - 检查plist文件中的用户名路径是否正确
- 重启launchd服务:
launchctl unload ~/Library/LaunchAgents/com.user.sleepwifi.plist然后重新load
6.2 Wi-Fi无法正常关闭
可能是网络接口名称不同:
networksetup -listallhardwareports将脚本中的en0替换为实际的Airport接口名
6.3 蓝牙设备连接异常
建议:
- 在脚本中添加2秒延迟后再启用蓝牙
- 对于Magic Keyboard等设备,可能需要先断开再连接:
blueutil --disconnect 40-ED-98-A1-B2-C3 sleep 1 blueutil --connect 40-ED-98-A1-B2-C37. 替代方案对比
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秒延迟,确保系统完全唤醒后再恢复蓝牙连接。