Mac電腦不睡眠的問題,貌似簡單其實水不淺,尤其是它有點怪異惱人,可謂是Mac典型的最詭異的問題之一了,在Windows視窗世界,這個似乎不是一個問題,到了Mac了幾乎就成了痼疾了。
雖然蘋果有官方文檔講述這個問題的解決方案,還算比較的詳細:如果您的 Mac 不會進入睡眠或者保持睡眠狀態。但這個問題的詭異就在於,其表象看上去一樣,導致表象的軟體硬體因素卻千差萬別,看看官方文檔,你會覺得:瓦,太複雜了。如果一個人能把文檔中所有的詳細步驟都記下來,在網上是不是也是大拿一個層級的了?
而為了能夠找到問題的根本,系統的內在因素就是我們關心的。為了能夠協助大家解惑答疑-本文希望做到的,本文試圖從多個方面盡量詳盡地分析可能造成此類問題的原因,並運用OSX提供的系統方法來監測和甄別問題的具體原因,並嘗試盡量給出解決辦法。其實,反過來說也涉及到了如何讓蘋果機不進入睡眠的各種可能,比如使用現成軟體,或者系統內部支援的命令,甚至自己編程實現也可以。總之,咱們在研讀原蘋果官方文檔的基礎上,可以進一步,瞭解和作業系統內部設定,做到對蘋果機控制自如。
因為本文多數內容涉及硬體和系統內部運行機制以及對系統資訊的分析和操作,所以不適合普通使用者,最好在有經驗的技術人員的協助下進行,並且理解相關說明內容再變更系統設定。
一般因素:
我們還是羅列一下吧,普通軟體可能是最常見的原因,比如可以看看下面進行排查:
看到第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 1Listed 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 foreverLocalized=THE CAFFEINATE TOOL IS PREVENTING SLEEP. pid 25(powerd): [0x0000000100000185] 00:15:58 PreventUserIdleSystemSleep named: "com.apple.powermanagement.ttyassertion" Details: /dev/ttys000Localized=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=TimeoutActionReleaseKernel 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: 系統時鐘訊息,比如設定的定時能源設定
為了禁止接受Wake-on-Lan資料包,實用下面命令:
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相關說明,比如這裡。