OSX: Mac不睡眠的排查
Mac电脑不睡眠的问题,貌似简单其实水不浅,尤其是它有点怪异恼人,可谓是Mac典型的最诡异的问题之一了,在Windows窗口世界,这个似乎不是一个问题,到了Mac了几乎就成了痼疾了。
虽然苹果有官方文档讲述这个问题的解决方法,还算比较的详细:如果您的 Mac 不会进入睡眠或者保持睡眠状态。但这个问题的诡异就在于,其表象看上去一样,导致表象的软件硬件因素却千差万别,看看官方文档,你会觉得:瓦,太复杂了。如果一个人能把文档中所有的详细步骤都记下来,在网上是不是也是大拿一个级别的了?
而为了能够找到问题的根本,系统的内在因素就是我们关心的。为了能够帮助大家解惑答疑-本文希望做到的,本文试图从多个方面尽量详尽地分析可能造成此类问题的原因,并运用OSX提供的系统方法来监测和甄别问题的具体原因,并尝试尽量给出解决办法。其实,反过来说也涉及到了如何让苹果机不进入睡眠的各种可能,比如使用现成软件,或者系统内部支持的命令,甚至自己编程实现也可以。总之,咱们在研读原苹果官方文档的基础上,可以进一步,了解和操作系统内部设置,做到对苹果机控制自如。
因为本文多数内容涉及硬件和系统内部运行机制以及对系统信息的分析和操作,所以不适合普通用户,最好在有经验的技术人员的帮助下进行,并且理解相关说明内容再变更系统设置。
一般因素:
我们还是罗列一下吧,普通软件可能是最常见的原因,比如可以看看下面进行排查:
- 是否iTunes播放音乐,它会禁止Mac电脑进入睡眠,以保持音乐的播放
- Dropbox在上传/下载文件, 可以禁止LAN sync来解决.
- 卸载Drobo Dashboard.
- 退出Google Drive.
- 其他的软件,如smcFanControl程序。
- 还有专门禁止睡眠的软件,如:InsomniaX,Caffeine,NoSleep和wimoweh等等
- 系统资源共享,比如互联网/文件共享等
看到第6条了,如果你希望使用现成软件来不让机器睡眠,那么这些软件可以考虑。
正文开始:
其实,不睡眠的根本原因有两个方面可能,一个是某个程序禁止系统进行睡眠,它是通过对系统所支持的断言(assertions)机制来实现的,下面会详细说;另一种情况是Mac虽然睡眠了后来接收到了唤醒消息,因为用户可能无意或者忘记或者没有意识到这些设置产生的影响,造成系统对特殊信号进行系统唤醒响应。所以,下面从两个方面来说明,如何下手检查。
在进一步分析之前,最好确认,系统是否设置了睡眠(是否禁止),可以到节能系统配置中查看,或者使用OSX提供的能源管理的命令pmset。对pmset的理解和使用,能帮助我们对苹果电脑的电源配置情况进行详尽了解并提高自由控制度,后面我们也是主要依靠这个命令来展开工作。
最基本的,用下面命令来查看当前的能源配置情况:
pmset -g或者是
pmset -g custom
前者只显示当前电源的配置情况,后者可以分别对电池和外接电源的不同配置显示。
利用上面的命令,看看sleep的配置值,如果是0,那么就是禁止睡眠,非零就是系统空闲的多少分钟后进入睡眠。
断言接口:
断言是系统底层IO对能源管理机制的对应用程序的一个接口,是在IOPMLib中定义的,官方文档写道:" access to common power management facilities, like initiating system sleep, getting current idle timer values, registering for sleep/wake notifications, and preventing system sleep."
为了能够更详细地排查到底是那个程序设置了断言阻止系统睡眠,可以通过查看当前系统断言的情况:
/usr/bin/pmset -g assertions
现在通过一个实例来分析,下面是一个典型的场景的断言情况:
Assertion status system-wide: PreventUserIdleDisplaySleep 1 CPUBoundAssertion 0 PreventSystemSleep 1 PreventUserIdleSystemSleep 1 InternalPreventDisplaySleep 1 ExternalMedia 0 UserIsActive 1 ApplePushServiceTask 0 BackgroundTask 1 Listed by owning process: pid 2922(screensharingd): [0x00000005000002b1] 00:04:37 NoDisplaySleepAssertion named: "Nameless (via IOPMAssertionCreate)" pid 44(mds): [0x0000000c00000133] 00:20:38 BackgroundTask named: "com.apple.metadata.mds" pid 2924(ScreensharingAg): [0x00000005000002bf] 00:00:15 NoDisplaySleepAssertion named: "screen sharing wake display" pid 2924(ScreensharingAg): [0x0000000a000002ba] 00:00:05 UserIsActive named: "screen sharing wake display" pid 2520: [0x0000012c000009d8] PreventUserIdleSystemSleep named: "com.apple.audio.‘AppleHDAEngineOutput:1B,0,1,2:0‘.noidlesleep"
pid 2423(caffeinate): [0x0000000800000292] 00:09:13 PreventSystemSleep named: "caffeinate command-line tool" Details: caffeinate asserting forever Localized=THE CAFFEINATE TOOL IS PREVENTING SLEEP. pid 25(powerd): [0x0000000100000185] 00:15:58 PreventUserIdleSystemSleep named: "com.apple.powermanagement.ttyassertion" Details: /dev/ttys000 Localized=A remote user is connected. That prevents system sleep. pid 25(powerd): [0x0000000d000002ae] 00:04:41 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 19 secs Action=TimeoutActionRelease pid 25(powerd): [0x0000000d000002af] 00:04:38 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 22 secs Action=TimeoutActionRelease pid 25(powerd): [0x0000000d000002b0] 00:04:38 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 22 secs Action=TimeoutActionRelease pid 25(powerd): [0x0000000d000002b6] 00:03:52 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 67 secs Action=TimeoutActionRelease pid 25(powerd): [0x0000000d000002b7] 00:03:52 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 67 secs Action=TimeoutActionRelease pid 25(powerd): [0x0000000d000002bc] 00:01:32 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 208 secs Action=TimeoutActionRelease pid 25(powerd): [0x0000000d000002be] 00:00:18 InternalPreventDisplaySleep named: "com.apple.powermanagement.delayDisplayOff" Timeout will fire in 282 secs Action=TimeoutActionRelease Kernel Assertions: None
它主要包括两个部分:
- 第一个部分,“Assertion status system-wide”,根据断言分类显示状态,每个状态如果被一个用户插入的断言所激活,会显示1;未激活的是0. 里面每一类断言都是会对系统产生影响的。常见的有PreventUserIdleSystemSleep和PreventUserIdleDisplaySleep。
- 第二部分,给你列出到底是哪个进程,产生了那一类的断言。
sudo kill <pid>
系统设置:
系统本来默认设置的一些系统行为,可能被改变:
比如关闭笔记本屏幕盖会让系统休眠,如果改变会影响这个行为,那么用这个命令来恢复默认行为:
sudo pmset -a lidwake 1
改变电源特性也会唤醒,这个行为用下面命令改变:
sudo pmset acwake 0
如果是有活动的ttys进程,比如终端程序甚至远程连接都有可能产生影响,用这个命令禁止:
sudo pmset -a ttyskeepawake 0
系统日志:
判断曾经被唤醒的动作,可以检查系统消息,运行命令:
/usr/bin/syslog | grep -i "Wake reason"
那么可能的消息有:
- EC.PowerButton PWRB (User): 用户按了电源键
- EHC2: 键盘按键或者鼠标移动
- EHC1: USB连接了iDevices
- ?: 接收到Wake-on-Lan数据包
- EHC/OHC/USB: USB或者火线设备
- LID0: 笔记本屏幕打开
- RTC: 实时时钟消息,比如设置的定时能源设置
sudo pmset -a womp 0
还有一种情况,就是因为某个程序的运行,延迟了睡眠的动作,这个可以这样着手:
pmset -g log | grep slowresponse如果它找到程序,那么就要运行类似下面的命令,并用文本编辑器软件打开,查找slowresponse来查看,到底是哪个程序延迟。比如下面的结果:
Domain: applicationresponse.timedout - Message: Kernel cupsd com.apple.powermanagement.applicationresponse.timedout 30000 ms - Time: 30/03/10 19:06:55 HAEC - Signature: cupsd - UUID: EDA8296C-E84D-4B86-8AE9-5321B8676227 - Result: Noop - Response time (ms): 30000
这个是打印机程序持续尝试打印造成睡眠延迟的。
编程:
最后补充一下,对于需要编程改变睡眠特性的,参见Apple的官方IOPMLib中的Assersions相关说明,比如这里。