58

So I saw a lots of old discussion on this topic, but I'm trying to find out an actual solution that still works on Mojave / Catalina, without the use of external monitor/keyboard/mouse/with power adapter.

When looking up Amphetamine, they claimed that you can only do it when the 4 criteria are met, and cannot overridden it.

Amphetamine

But on the other hands, Anti Sleep provide the feature in their pro version...

enter image description here

So, which one gets the real deal ? Is Anti Sleep lying about it or Amphetamine (and all other caffeine app on the appStore) is out of date ?

I also heard about InsomniaX and built-in caffeine but it's really not user friendly, and appear not to be supported anymore...

1

4 Answers 4

102

You can accomplish this in terminal. No additional software needed.

Display global power settings:
pmset -g

System-wide power settings:
Currently in use:
 lidwake              1
 autopoweroff         1
 standbydelayhigh     86400
 autopoweroffdelay    28800
 proximitywake        1
 standby              1
 standbydelaylow      10800
 ttyskeepawake        1
 hibernatemode        3
 powernap             1
 gpuswitch            2
 hibernatefile        /var/vm/sleepimage
 highstandbythreshold 50
 womp                 0
 displaysleep         10
 networkoversleep     0
 sleep                1 (sleep prevented by sharingd)
 tcpkeepalive         1
 halfdim              1
 acwake               0
 disksleep            10



To stop sleep entirely:
sudo pmset -a disablesleep 1

To revert, allowing sleep again:
sudo pmset -a disablesleep 0

6
  • Well, that was an easy one ! But then, why amphetamine claim it's impossible ? Thanks CJ !
    – Edd Growl
    Commented Jun 2, 2019 at 17:11
  • 2
    these settings are stored in the PRAM/NVRAM which is covered by the logic board and protected by Apple's System Integrity Protection. Thats why sudo is required for the command to execute.
    – CJ Dana
    Commented Jun 3, 2019 at 22:19
  • 15
    Be careful with this. It literally disables the sleep option on the Apple menu. When I used it and put my Mac away in my backpack at the end of the day, it kept running and got very hot. Before stopping work for the day, you'll have to allow sleep again with the ...disablesleep 0 option.
    – JESii
    Commented Dec 3, 2019 at 10:03
  • This is a fantastic solution. I can have my Mac running connected to a monitor, and my lid is closed and it is still running.
    – MikeyN0
    Commented Oct 30, 2020 at 5:28
  • It can really prevent sleep at the moment I close the lid, but it can't prevent system from going to sleep after 1 minute. Are there any more commands that can be used? Commented Apr 2, 2022 at 13:12
14

There is a built-in utility called caffeinate that will temporarily stop your Mac from going to sleep.

Open the Terminal app and run:

caffeinate -i -s

This will stop the Mac from sleeping while the command is running. Press Ctrl+C to quit it and restore normal sleep behavior. (Cmd+Q to quit the Terminal works as well.)

The -i option stops your system from going to sleep after a period of idleness, and -s is to stop it from sleeping when the lid is closed. (See also this answer.)

Note that keeping the system awake with the lid closed only works while you're connected to AC power. If you disconnect your charger, the Mac will sleep immediately. By my testing (on a 2021 M1 MacBook Air), if you reconnect the charger later, it will automatically wake up the Mac again, even without opening the lid.

See man caffeinate for more options.

2

I went a step further. I never want my MacBook to sleep, not even when I close the lid, unless I tell it to explicitly, so I want to have full control about this behavior. If I do so, I also want to make sure that it can sleep, as I experienced a few times that it should sleep, but it actually didn't sleep, because some process was preventing sleep. On top of that, I want it to run a script on shutdown as well as on sleep, for the latter I can use the Sleep Watcher, so this solution adapts it for the former case.

First I run:

sudo pmset -a disablesleep 1
sudo pmset -a displaysleep 0
sudo pmset -a sleep 0

Now the Mac will run forever, even when closing the lid. Nice to carry it around without AC power or whatever while its doing some tasks, or just being ready without any delay.

Then I put these aliases into my .zshrc:

alias cansleep="test ! $(pmset -g assertions | grep SystemSleep | grep -v 0)"
alias sleepnow="sudo sh -c 'pmset -a disablesleep 0 && pmset sleepnow && pmset -a disablesleep 1'"
alias gosleep="test cansleep && sleepnow || open -a 'Activity Monitor'"
alias poweroff='test -x "$HOME/.sleep" && "$HOME/.sleep"; osascript -e '"'"'tell app "System Events" to shut down with state saving preference'"'"
alias reboot='test -x "$HOME/.sleep" && "$HOME/.sleep"; osascript -e '"'"'tell app "System Events" to restart with state saving preference'"'"

From now on I start to control the boot and sleep behavior from the terminal exclusively:

  • sleepnow: Try to sleep (similar behavior to closing the lit before the changes, a process could prevent sleep)
  • gosleep: Check if you can sleep, if not, open the Activity Monitor to show you sleep-preventing processes, otherwise go sleep (a successful sleep is indicated by the screen turning black)
  • poweroff: Graceful shutdown (as if you would shutdown from the apple menu as shutdown is not graceful), poweroff will also try to run the .sleep script, making its behavior like sleep while using the Sleep Watcher for consistency
  • reboot: Like poweroff, but graceful restart. Also runs the .sleep script

As you can see, I also wanted to include my personal routines prior sleeping that I trigger using the Sleep Watcher. Things like turning off bluetooth, now it's turned off prior shutdown or reboot as well.

This is a result of transitioning to powering off my MacBook whenever I want to put it into the bag, because despite checking for sleep preventing processes I have to admit, the solution is still error prone and I ended up with a hot device in the bag. I think Apple did a terrible job here. A closed lid should end up with deep sleep within the next 5 minutes, but Apple allows processes to prevent sleep, so the risk of slowly damaging your device through overheat is great.

Lastly, to avoid the required password on sleepnow, I can take Randomblock1's approach and run this in order (line by line):

export ME="$USER"
sudo -E su
echo "$ME ALL=(ALL) NOPASSWD: /usr/bin/pmset" > /private/etc/sudoers.d/pmset

and use

alias sleepnow="sudo pmset -a disablesleep 0 && pmset sleepnow && sudo pmset -a disablesleep 1"

instead. You need to have the su account enabled for that approach. Alternatively sudo visudo works for that as well. A reboot is required to source the sudoers again.

5
  • 1
    What's "lit"???
    – yssup
    Commented Oct 2, 2023 at 6:15
  • 1
    @yssup My solution. Jokes aside, I had some bug in my head when i consistently called the lid "lit". Commented Oct 3, 2023 at 0:09
  • 1
    well you also said "overhead" instead of "overheat".
    – yssup
    Commented Oct 3, 2023 at 7:18
  • 1
    @yssup Thank you for proof reading my answer, which was clearly my job. I appreciate it! Commented Oct 3, 2023 at 20:06
  • This answer allowed me to close the lid and use an external monitor without the screen blacking out or sleeping. Nothing else was working.
    – cloudxix
    Commented Aug 18 at 1:26
1

Adding on to CJ's answer, you can create a shell script to automatically manage pmset enabling and disabling sleep. https://apple.stackexchange.com/a/270835/408131

#!/bin/bash
#***************************************************************************
#*** noz - prevent laptop from sleeping when lid is closed
#***************************************************************************

#***** set some defaults *****
BATTERY_SLEEP=5 # in minutes
DEF_WAKE_LEN=300 # in seconds

#***** determine timeout value *****
timeout_len=${1:-$DEF_WAKE_LEN}

function prevent_sleep() {
    echo
    echo -n "Preventing sleep for $timeout_len seconds; press <enter> to continue..."

    sudo pmset -b disablesleep 1
    sudo pmset -b sleep 0
}

function enable_sleep() {
    # $1: <enter> = 0, timeout = 1, Ctrl-C = undef

    #----- insert a newline for timeout or Ctrl-C -----
    if [[ ${1:-1} -eq 1 ]]; then    echo; fi
    echo "Restoring previous battery sleep setting: $BATTERY_SLEEP"

    sudo pmset -b disablesleep 0
    sudo pmset -b sleep $BATTERY_SLEEP

    #----- sleep on timeout only -----
    if [[ ${1:--1} -eq 1 ]]; then   sudo pmset sleepnow; fi
    exit
}

#***** prevent it from sleeping *****
prevent_sleep

#***** trap Ctrl-C *****
trap enable_sleep INT

#***** wait for an enter *****
read -t $timeout_len
rc=$?

#***** re-enable normal sleep *****
enable_sleep $rc

The shell script will disable sleeping until you hit the Enter key, at which point it will re-enable the sleep settings (alternately, you can hit Ctrl-C and achieve the same thing). It will also set a timeout (defaults to 300 seconds/5 minutes) after which the sleep settings will automatically be re-enabled, and the laptop will be forced to go to sleep. While this would be a pain if you're using your laptop in a meeting, it will be a lifesaver if you forgot and put your laptop in your bag to go home.

Astute readers will note that these commands require sudo; sadly, that's unavoidable AFAIK. What I've done on my system is to make it so that I don't have to enter my password to run pmset as root. To do that, edit the sudoers file (sudo visudo) and add this line:

YOURUSERNAME ALL=(ALL) NOPASSWD: /usr/bin/pmset

replacing "YOURUSERNAME" with your username. You could probably achieve the same result (i.e. running the script without having to enter your password) by running the shell script SETUID, but I don't like doing that; opening up this one command via sudoers seems less risky to me.

To run the script, stick it in a directory on your PATH and invoke it as such:

noz [<timeout in seconds>]

When you get to where you're going, simply hit Enter or Ctrl-C and you're good to go. And if you forget about it, it will automatically reset and sleep.

You can also set up an Automator Quick Action, tell it to execute noz, and bind it to a hotkey.

2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .