Prevent machine from sleeping when SSH connections are on
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:
So create a file
/etc/pm/sleep.d/05_ssh_keepawake
.Put a shebang (
#!/bin/sh
) and the code mentioned in the question in this file.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)
.
Combining two related answers (here and here), here's an /etc/pam_session.sh
that does the trick on Ubuntu 19.10 (at least):
#!/bin/sh
#
# This script runs when an ssh session opens/closes, and masks/unmasks
# systemd sleep and hibernate targets, respectively.
#
# Inspired by: https://unix.stackexchange.com/a/136552/84197 and
# https://askubuntu.com/a/954943/388360
num_ssh=$(netstat -nt | awk '$4 ~ /:22$/ && $6 == "ESTABLISHED"' | wc -l)
case "$PAM_TYPE" in
open_session)
if [ "${num_ssh}" -gt 1 ]; then
exit
fi
command=mask
;;
close_session)
if [ "${num_ssh}" -ne 0 ]; then
exit
fi
command=unmask
;;
*)
exit
esac
logger "${command}ing sleep and suspend targets (num_ssh=${num_ssh})"
sudo systemctl ${command} sleep.target suspend.target
Make sure to add the line:
session optional pam_exec.so quiet /etc/pam_session.sh
to /etc/pam.d/sshd
in the session
section, and make the /etc/pam_session.sh
script executable:
chmod +x /etc/pam_session.sh
Note that the /etc/pam_session.sh
script appears to run as the the user logging in or out, so that user requires sudo
access to mask/unmask systemd targets.