#!/bin/sh # # Shutdown system if it has been idle for 1 hour and no active users are logged # in. # # Usage: This script is mainly used on a home server used for building FreeBSD # World and kernels. As soon it is done it can shutdown if not being used # anymore. The system has Wake-On-Lan support and can thus be activated again # from remote. # # Please run from cron every CRON_INTERVAL minutes: # */5 * * * * * /usr/local/bin/power-saver # # Rick van der Zwet # CRON_INTERVAL=5 MAX_LOAD=0.10 MAX_IDLE=45 # Abuse this trick to force a quicker shutdown by ignoring some users IDLE_USER=${1:-1} # Shutdown delay is NOT considered idle time, but just a save guard. SHUTDOWN_DELAY=${2:-15} # Stored as DAT_FILE='/tmp/power-saver.dat' # Current values EPOCH=`date "+%s"` LOAD_15=`sysctl vm.loadavg | awk '{print $5}'` # Empty file needs to be created and filled echo "$EPOCH $LOAD_15" >> $DAT_FILE || exit 1 # Check if countdown has already been started ps -x | grep -q '[0-9] shutdown' && exit 0 # Check if all users are no longer active SHORTEST_IDLE=`w -ih | awk -vIDLE_USER=$IDLE_USER '{if (NR == IDLE_USER) print $5}'` # Hack to make sure time is always in minutes SHORTEST_IDLE_IN_MIN=`echo $SHORTEST_IDLE | awk -F: '{if (NF > 1){print $1 * 60 + $2}else{print $1}}'` if [ -z "$SHORTEST_IDLE_IN_MIN" ]; then # No users are currently logged in continue elif [ "$SHORTEST_IDLE_IN_MIN" = "-" ]; then # User is still active an minute ago exit 0 elif [ $SHORTEST_IDLE_IN_MIN -le $MAX_IDLE ]; then # User is still active less than MAX_IDLE ago exit 0 fi # Count the amount entries we are current on our way IDLE_COUNTS=`awk -vMAX_LOAD=$MAX_LOAD -vMAX_IDLE=$MAX_IDLE -vEPOCH=$EPOCH \ 'BEGIN{MIN_TIME=EPOCH-MAX_IDLE * 60;s=0}{if ($1 > MIN_TIME && $2 < MAX_LOAD){s += 1}}END{print s}' $DAT_FILE` # We are idle for over $MAX_IDLE time, starting shutdown if [ $IDLE_COUNTS -ge `expr $MAX_IDLE / $CRON_INTERVAL` ]; then shutdown -p "+$SHUTDOWN_DELAY" "Cancel: sudo killall -SIGTERM shutdown" fi