systemdが動いている一般的なLinuxで, SSH接続しているユーザーが存在するときにスリープ (サスペンド, ハイバネート) させない方法です.
systemdが標準で入っている昨今のLinuxディストーション (Ubuntuとか) であれば, 適用可能です. ただ, デスクトップ向けにセットアップしたLinuxマシンでもなければ, サスペンド/ハイバネートといった設定はしないので, ややニッチな話題です.
背景
デスクトップ用途で稼働させているLinuxの場合, 省電力のための設定を有効にしておくことが多いかと思います (操作が行われないまま一定時間経過したら, サスペンド/ハイバネートさせるとか).
書斎にあるLinuxがインストールされたデスクトップPCへ, リビングのノートパソコンからちょっとした用事があるときにSSH接続することがありますが, ここが問題. そういったSSH接続しての作業中は無操作状態とみなされて, 時間がきたらサスペンドされてしまうのです.
横着せずに省電力設定を止めるなりすればいいだけのことですが, ここはsystemdらしいアプローチでの解決方法をとってみました.
確認に使った環境
Archlinuxで動作確認しています. デスクトップ環境はGNOMEで, GNOME標準の設定画面から省電力設定をおこなってます.
systemdが入っている昨今のほとんどのLinuxディストリビューションなら同じことができるはず.
やりかた
次のようなファイルを作成します. systemdのユニットファイルと呼ばれるものです.
作るディレクトリは記載の通り /etc/systemd/system
.
[kosuke@cf-sx1 ~]$ cat /etc/systemd/system/inhibit-sleep.service
[Unit]
Description=Inhibit sleep when ssh logged
Before=sleep.target
[Service]
Type=oneshot
ExecStart=/usr/bin/sh -c '! who | grep -q "(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\})"'
[Install]
RequiredBy=sleep.target
スリープフックと呼ばれるもので, スリープ (サスペンド, ハイバネート) する前にExecStartで指定したコマンドが実行されるようになります.
whoコマンドSSHログイン中のユーザーがいないかチェックして, もしいたら終了コード0以外にして後続処理を動かさないことで実現します.
ファイルを作成したら, 次のコマンドでユニットを有効にします.
# systemctl enable inhibit-sleep.service
これで準備OKです.
動作確認してみる
対象のマシンは20分でサスペンドするように設定されています.
動作確認したあとのログを見てみましょう.
[kosuke@cf-sx1 ~]$ journalctl -f -usleep.target
-- Journal begins at Fri 2020-07-24 20:13:01 JST. --
3月 03 23:06:33 cf-sx1 systemd[1]: Reached target Sleep.
3月 03 23:06:45 cf-sx1 systemd[1]: Stopped target Sleep.
3月 03 23:07:18 cf-sx1 systemd[1]: Dependency failed for Sleep.
3月 03 23:07:18 cf-sx1 systemd[1]: sleep.target: Job sleep.target/start failed with result 'dependency'.
3月 03 23:28:38 cf-sx1 systemd[1]: Dependency failed for Sleep.
3月 03 23:28:38 cf-sx1 systemd[1]: sleep.target: Job sleep.target/start failed with result 'dependency'.
3月 03 23:48:39 cf-sx1 systemd[1]: Reached target Sleep.
3月 03 23:49:14 cf-sx1 systemd[1]: Stopped target Sleep.
これだけだとわからないので, 少しずつ説明してみます.
これは設定を入れた後にSSHログインユーザーがいない状態でサスペンドコマンド systemctl suspend
でサスペンドさせてみた結果です.
Reached でサスペンド, Stopped で復帰です.
3月 03 23:06:33 cf-sx1 systemd[1]: Reached target Sleep.
3月 03 23:06:45 cf-sx1 systemd[1]: Stopped target Sleep.
次にSSHでログインしているユーザーがいるときに, 同じコマンドでサスペンドを試みます. すると, sleep.targetに依存させるよう追加/設定した前述のユニットファイルが失敗するので, スリープも実行されなくなります.
3月 03 23:07:18 cf-sx1 systemd[1]: Dependency failed for Sleep.
3月 03 23:07:18 cf-sx1 systemd[1]: sleep.target: Job sleep.target/start failed with result 'dependency'.
このまま20分ほど放置……. ここでも同じようにスリープされません.
3月 03 23:28:38 cf-sx1 systemd[1]: Dependency failed for Sleep.
3月 03 23:28:38 cf-sx1 systemd[1]: sleep.target: Job sleep.target/start failed with result 'dependency'.
ここでSSH接続しているユーザーをログアウトさせます. さらに20分ほど経過すると, 今度はサスペンドされました.
3月 03 23:48:39 cf-sx1 systemd[1]: Reached target Sleep.
3月 03 23:49:14 cf-sx1 systemd[1]: Stopped target Sleep.
参考資料
たいていのことはArchWikiに書いてある気がする.