0

Idle is defined as when no foreground program is running and the terminal is waiting for user input, but the user does not make any input.

Actually, my ultimate goal is: shutdown when all SSH sessions are idle and x-window is also idle.
The idle time of x-window can be determined with xprintidle. So for now I just need to determine if all SSH sessions are idle or not.
I've looked for many ways to determine if a machine is idle in Linux, but most of them are based on x-window to determine if the desktop is idle.

  • There used to be a program called timeoutd which would log out users who had been idle for a configurable amount of time. It used to be pretty popular to stop users from hogging scarce resources like modem dial-in lines. I haven't seen it for many years and I don't think it's maintained any more. Anyway if you could find that and recompile it for a modern distro (or find an alternative that does the same thing), you could shutdown when there are no ssh sessions logged in. – cas Oct 20 '21 at 15:32

1 Answers1

-1

in /etc/ssh/sshd_config

# default values
ClientAliveInterval                        0
ClientAliveCountMax                        3

If you set ClientAliveInterval to 600 {seconds} along with ClientAliveCountMax to 0 then that will close any SSH session that has been idle for 10 minutes. By using this mechanism you could have any SSH session cleanly close after a specific timeout or idle period of your choosing. Then check to see if there are any SSH sessions or processes present and if not then do a shutdown.

Recommend you also read up on those two SSH parameters before using them to be sure,

https://man.openbsd.org/sshd_config

What do options `ServerAliveInterval` and `ClientAliveInterval` in sshd_config do exactly?

because someone doesn't believe me... edit /etc/ssh/sshd_config to have ClientAliveInterval 61 and ClientAliveCountMax 0 and then have the below script run via crontab every minute and watch your machine shut down

#!/bin/bash

ssh_idle_shutdown.bash

the first num (a) in file /var/run/sshidleshutdown.txt is 0 or 1 based on if a ssh connection has happened

if a == 1 and count == 0 then do something

if [ ! -f /var/run/sshidleshutdown.txt ] then echo 0 > /var/run/sshidleshutdown.txt fi

count=netstat -tnpa | grep 'ESTABLISHED.*sshd' | wc -l

str=head /var/run/sshidleshutdown.txt astr=${str:0:1} a=$((astr))

if [ $a -eq 0 ] && [ $count -gt 0 ] then echo 1 > /var/run/sshidleshutdown.txt elif [ $a -eq 1 ] && [ $count -eq 0 ] then echo -n "ssh idle condition met system shutdown called at " >> /var/log/sshidleshutdownlog.txt date >> /var/log/sshidleshutdownlog.txt rm -f /var/run/sshidleshutdown.txt

execute /sbin/shutdown

fi

put this in /etc/crontab

1 * * * * *  root   /path_to/ssh_idle_shutdown.bash

and also do

chown root.root  /path_to/ssh_idle_shutdown.bash
chmod 700 /path_to/ssh_idle_shutdown.bash

this is letting the SSH server identify what idle sessions are, and then the ssh server is closing them. Once we have seen at least one established ssh session then we begin checking until no ssh sessions are left via netstat, because the ssh server will have closed idle sessions based on ClientAlive Interval and ClientAliveCountMax in sshd_config. Adjust ClientAliveInterval and /etc/crontab frequency for running this ssh_idle_shutdown.bash accordingly.

ron
  • 6,575
  • So wrong. This answer explains why. – Kamil Maciorowski Jan 10 '24 at 09:27
  • let the US government know they are wrong too! https://www.stigviewer.com/stig/red_hat_enterprise_linux_8/2021-06-14/finding/V-244525 – ron Jan 10 '24 at 13:08
  • Within the sshd_config the product of the values of "ClientAliveInterval" and "ClientAliveCountMax" are used to establish the inactivity threshold; – ron Jan 10 '24 at 13:09
  • This forces the client to respond, the method only detects inactivity meaning "the client mysteriously disappeared from the network". The question is about when "the terminal is waiting for user input, but the user does not make any input". If only the network connection is fine, your method will make the server and the client exchange a "ping", so they will know the other side is still there. The client will respond even if it's "idle" by the definition of the OP. – Kamil Maciorowski Jan 10 '24 at 13:50
  • no it does not force the client to respond. if the client does not respond, if in putty under connection you have seconds between keepalives set to 0 the default then no keepalive ping will be sent, the ssh server will kill those sessions that have been idle for ClientAliveInterval seconds. Try it. And like I said, not in so many words, write a script to run in the background that looks for no ssh connections [because idle ones will have been killed via ClientAliveInterval and then if num_ssh_sessions == 0 /sbin/shutdown. – ron Jan 10 '24 at 19:27
  • And take into account the starting case of zero ssh sessions because nobody ssh'd in yet. – ron Jan 10 '24 at 19:27
  • https://unix.stackexchange.com/questions/92560/list-all-connected-ssh-sessions – ron Jan 10 '24 at 19:30
  • I think seconds between keepalives in PuTTY is like ServerAliveInterval in ssh. Keep-alive messages in SSH may be SSH_MSG_GLOBAL_REQUEST and per RFC 4254 "both the client and server MAY send global requests at any time, and the receiver MUST respond appropriately". So if one end uses *Alive*, the other must respond. No response means the other end is AWOL. This is what the mechanism detects and formally disconnects. It does not detect situations where a user takes a break from typing on the client machine. – Kamil Maciorowski Jan 10 '24 at 19:50
  • I can see your script. With what exact connection(s) (ssh command(s)) have you tested it? What do you do to keep them "idle"? What do you do to keep them "busy" (to make sure they get terminated only when idle)? How do you know the server part of each idle connection gets closed because of being idle? My test is simple: ssh -vvv -N …. This is extremely idle: after authentication and such, only keep-alive packets flow (until future rekeying, I guess). The server does not end the connection as "idle". The packets alone make the connection non-idle. It's been over 60x ClientAliveInterval. – Kamil Maciorowski Jan 10 '24 at 22:54
  • I don't know what you are talking about at this point. I've explained enough. – ron Jan 11 '24 at 14:52
  • i created an idle SSH connection. Your ClientAlive* settings not only fail in detecting its idleness, they keep it alive. I'm not surprised, these packets are exactly to keep connections alive. They are not a way to detect connections that are idle by the OP's definition. – Kamil Maciorowski Jan 11 '24 at 16:07
  • you're doing something wrong. Like I said, go tell the USG everything they're wrong too. – ron Jan 11 '24 at 20:54
  • Ah, argumentum ab auctoritate. AFAIK RHEL used to have a misleading claim in its security guide. See the bug report and the discussion there. Is it possible the source you linked to has followed the buggy guide? I also note the handling of ClientAliveCountMax=0 chagned in OpenSSH. What is your SSH server and the version of it? – Kamil Maciorowski Jan 12 '24 at 04:27
  • While digging, I discovered ChannelTimeout and UnusedConnectionTimeout. They are relatively new (OpenSSH 9.2, 2023-02-02). These are designed to detect inactivity (as opposed to disappearance of the client detected by ClientAlive*) and they probably can be used to solve the question here. I learned something new, thank you. Are you going to investigate the new options and fix your answer? I will gladly vote up then. – Kamil Maciorowski Jan 12 '24 at 04:41