Automatically Shutdown Idle Server


howto idle shutdown

Premice

Imagine you started a server and stopped using the service on it (e.g. some gameserver, openvpn, …) but you can just not now shut it down manually?

Let’s setup a quick bash script that monitors network connections to that service and shutdown the server when it is idle for some time.

Idea

We can run a script via cronjob (every e.g. 5 minutes)

If the script does not find any connected clients the first time, it will save the current time (in seconds since epoch) to a file in /tmp. The next calls to the script it will check if

The script

 
#!/bin/bash
 
#this script checks how long {whatever} server is idle, and after 30 minutes will power off the machine
 
DEBUG="True"
PORT=1234	# TCP port number your server is listening to
 
#file that tracks since when server is idle, gets removed after reboot (cron entry)
# add cron entry: '@reboot /usr/bin/rm -f /tmp/myServer_idle_time'
track_idle_time=/tmp/myServer_idle_time
max_idle_time=1800      # idle time in seconds, 1800 is 30 minutes, 3600 is 1 hour
 
#if connected_clients is empty there are no clients connected
connected_clients=$(sudo netstat -an | grep "$PORT" | grep ESTABLISHED)
 
if [[ -n "$connected_clients" ]]; then
    if [[ $DEBUG == "True" ]]; then echo "there are still users connected to the server. removing $track_idle_time"; fi
    rm -fv $track_idle_time
else
    # idle file does not exist yet? create it and put seconds since 1970-01-01 00:00:00 UTC into it
    if [[ ! -f "$track_idle_time" ]]; then
        /usr/bin/date "+%s" > $track_idle_time
    else
        time_idle_since=$(grep -Eo '([0-9]+)' $track_idle_time)
        time_idle=$(expr $time_idle_since + $max_idle_time)
        now=$(/usr/bin/date "+%s")
        if [[ $now -gt $time_idle ]];then
            if [[ $DEBUG == "True" ]]; then echo "We are idle more than $max_idle_time. powering off machine"; fi
            sudo /usr/sbin/shutdown -h now
        fi
    fi
fi
 
 

Cron entries

Add the following cron entries:

(do “crontab -e” if unsure)

(the first removes the file we keep track at boot and the other is our script that runs every 5 minutes)

 
@reboot /usr/bin/rm -f /tmp/myServer_idle_time
*/5 * *  * * /bin/bash /home/user/auto_poweroff/check_poweroff.sh >> /home/user/auto_poweroff/auto_poweroff.log
 

Variants

openvpn

For an openvpn server you can look at the actual clients that are connected (instead of using netstat). Change line 14 to

 
connected_clients=$(sudo /bin/grep "^CLIENT_LIST" /etc/openvpn/server/openvpn-status.log)
 

(change the path to the location of your openvpn status log)