Ubuntu – Prevent machine from sleeping when SSH connections are on

power-managementsshsuspend

I am trying to save power by switching desktops to suspend mode when they are inactive. But many desktops are also accessed via SSH by their owners. There is a wakeonlan solution deployed to enable owners to switch on the machine, but the problem is that machines will auto-suspend again in 10 minutes, even though the SSH connection is on.

What I am trying to do is to include the active SSH sessions in the "activity" definitions.

The question is can it be done via setting a polkit rule? Can it be done via putting a script that runs before the actual suspend, and aborts it if SSH sessions are found? I need a clean legit way of doing this. If not that, then hacky ways are also welcome.

Current naive hacky solution: edit /usr/sbin/pm-suspend:

#check for SSH sessions, and prevent suspending:
if [ "$(who | grep -cv "(:")" -gt 0 ]; then
    echo "SSH session(s) are on. Not suspending."
    exit 1
fi

This serves the purpose. But I don't know when an update will overwrite the file /usr/sbin/pm-suspend. I also don't know how this will work with other suspend implementations like tuxonice.

Best Answer

Until Ubuntu 14.10 (Upstart-based)

Have a look at pm-action(8) and search for /etc/pm/sleep.d in section “FILES”. If one of these scripts returns with a non-zero exit status, suspension is prevented.

Updated instructions for clarity:

  1. So create a file /etc/pm/sleep.d/05_ssh_keepawake.

  2. Put a shebang (#!/bin/sh) and the code mentioned in the question in this file.

  3. Set execute permissions on it:

    chmod +x /etc/pm/sleep.d/05_ssh_keepawake
    

Since Ubuntu 15.04 (systemd-based)

systemd doesn’t use pm-utils to manage its power state hooks but has its own infrastructure to the same end. Sleep inhibitor checkers are no longer executed on sleep but must be set by the action that inhibits sleep (see 1).

As such you’d have to add commands to the SSH session log-in and log-out that registers a sleep inhibitor with systemd (e. g. via systemd-inhibit(1)) and later releases the inhibitor. If somebody knows how to hook into SSH log-in and log-out, I’d welcome a comment or edit so that we could work out the relevant steps and commands.

The following section is work in progress – Only use it when you know what you’re doing!

You might be able to write a systemd unit /etc/systemd/system/ssh-inhibt-sleep.service that makes itself a dependency of sleep.target using the RequiredBy option. If your new unit fails (with a non-zero exit status from its invoked process), it will make sleep.target and thus the subsequent sleep action.

[Unit]
Description=Check for running SSH sessions and, if any, inhibit sleep
Before=sleep.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c '! who | grep -qv "\(:0\)"'

[Install]
RequiredBy=sleep.target

As always you need to activate systemd units for them to take effect:

sudo systemctl enable ssh-inhibt-sleep.service

For more info see systemd.unit(5) and systemd.service(5).

Related Question