為何 Mac 合上上蓋後仍未進入睡眠:兩個睡眠陷阱
Why your Mac stays awake after you close the lid: two sleep traps
Mac 合上上蓋後仍可能因睡眠受阻而保持運作,文章整理了兩種原因並提供檢查及修正方法。若合蓋時睡眠被阻止,`pmset disablesleep 0` 不會令 macOS 重試合蓋睡眠;而 `.userInitiated` 包含 `.idleSystemSleepDisabled`,可令未結束活動的常駐 App 阻止閒置睡眠。
I make Vigil, a Mac app that keeps the machine awake for long jobs, even with the lid closed. Most of the work turned out to be the opposite problem: getting the Mac to sleep again afterward. Here are two traps I measured, and the commands to check your own Mac.
Trap 1: turning sleep back on doesn’t put the Mac to sleep
Vigil holds the Mac awake with pmset disablesleep 1 and lets go with disablesleep 0. On 4 Sep I tested it on an M4 MacBook Air. I closed the lid at 20:27 and the hold ended at 20:42. At 22:50 the Mac was still awake, and hot, in a bag.
pmset -g explained it:
sleep 1 (sleep prevented by Claude, coreaudiod, powerd, sharingd, Sada)
Lid-close sleep is a one-time event at the moment the lid closes. If something blocks it then, macOS doesn’t try again when the block lifts. All that’s left is idle sleep, and any app holding an idle assertion stops that too.
The fix: when a hold ends while the lid is closed (AppleClamshellState is true), run pmset sleepnow as root right after disablesleep 0. Skip it if an external display is connected, because that person is using clamshell mode on purpose.
Trap 2: .userInitiated quietly blocks sleep
Sada, another of my apps, sat in that list above. Vigil later reported it had held the Mac awake for over 100 hours, and pmset -g assertions agreed:
pid 69298(Sada): 100:38:27 PreventUserIdleSystemSleep named: Sada sync responder
The cause was one line at launch, meant only to stop automatic termination:
ProcessInfo.processInfo.beginActivity(
options: [.userInitiated, .automaticTerminationDisabled],
reason: reason)
.userInitiated is a composite. It includes .idleSystemSleepDisabled, and nothing at the call site says so. A menu bar app that never ends the activity keeps your Mac from idle sleeping for as long as it runs.
To keep an app alive without touching sleep, use this instead:
[.suddenTerminationDisabled, .automaticTerminationDisabled]
Take .idleSystemSleepDisabled only for bounded work, and end the activity on every exit path. My release script for Sada now fails the build if .userInitiated shows up in beginActivity.
Check your own Mac
pmset -g | grep sleep
pmset -g assertions
The first shows who is blocking sleep. The second shows how long each one has held. A resident app with a timer in the hours is the one to look at.
If you run long jobs on a laptop, or just want to know what kept your Mac awake, Vigil is my app for both. I also send a short note when one of my Mac apps ships or gets a big update, twice a month at most: join the list here.
來源:DEV Community · dev.to