Every time your Mac wakes from sleep powerd
creates an InternalPreventSleep
assertion labeled com.apple.powermanagement.acwakelinger
with a 45 second timeout. That assertion ensures that even if your Mac needs to wake for 2 seconds to recieve a push notification that it stays on for 45 seconds.
Seemingly there's no way to control this. And recent versions of macOS love to wake quite frequently.
Forunately we can disable this. The built in pmset
tool has many undocumented features but thankfully it's open source
Cruicially there's an undocumented pmset disabledassertion
feature that just makes macOS ignore certain power assertions. To effectively disable acwakelinger
we just run this:
$ sudo pmset disableassertion InternalPreventSleep
And that's it. You can now observe that after waking your Mac goes back to sleeping nearly immediately. Renable it with:
$ sudo pmset enableassertion InternalPreventSleep // re-enable it
Warning: Disabling InternalPreventSleep
has worked fine for me in practice though it might cause issues for some. But disabling other assertions should be done carefully. I wouldn't recommend disabling UserIsActive
. In theory if you disabled all assertion types than your Mac would never wake from sleep.
Pro-tip: when a Mac is sleeping its ping ttl changes from 64 to 32. So you can check if its sleeping by pinging it from another computer:
$ ping chris-mbp.lan
64 bytes from 192.168.13.37: icmp_seq=0 ttl=64 time=5.703 ms
64 bytes from 192.168.13.37: icmp_seq=1 ttl=64 time=3.035 ms
64 bytes from 192.168.13.37: icmp_seq=2 ttl=32 time=2.063 ms # <--- Mac is now sleeping!
64 bytes from 192.168.13.37: icmp_seq=3 ttl=32 time=2.851 ms
Pro-top #2: The pmset -g assertionlog
command is very helpful. But it's hard to see the log stream live while your Mac is sleeping/waking so you can use netcat to monitor the log on another computer like this:
nc -lk 3333
pmset -g assertionlog | nc <ip of secondary mac> 3333
Now you'll see a live log of assertions on your secondary computer. Importantly this connection persists across sleeping cycles. Though if you're having trouble you can also do this:
while true; do timeout 5m pmset -g assertionlog | nc <ip of secondary mac> 3333 ; sleep 1; done
That'll restart the connection every 5 minutes assuming you have timeout
installed (brew install coreutils
)