[361] | 1 | #!/bin/sh
|
---|
| 2 | #
|
---|
| 3 | # Shutdown system if it has been idle for 1 hour and no active users are logged
|
---|
| 4 | # in.
|
---|
| 5 | #
|
---|
| 6 | # Usage: This script is mainly used on a home server used for building FreeBSD
|
---|
| 7 | # World and kernels. As soon it is done it can shutdown if not being used
|
---|
| 8 | # anymore. The system has Wake-On-Lan support and can thus be activated again
|
---|
| 9 | # from remote.
|
---|
| 10 | #
|
---|
| 11 | # Please run from cron every CRON_INTERVAL minutes:
|
---|
| 12 | # */5 * * * * * /usr/local/bin/power-saver
|
---|
| 13 | #
|
---|
| 14 | # Rick van der Zwet <info@rickvanderzwet.nl>
|
---|
| 15 | #
|
---|
| 16 |
|
---|
| 17 | CRON_INTERVAL=5
|
---|
| 18 | MAX_LOAD=0.10
|
---|
[363] | 19 | MAX_IDLE=45
|
---|
[361] | 20 |
|
---|
[362] | 21 | # Abuse this trick to force a quicker shutdown by ignoring some users
|
---|
| 22 | IDLE_USER=${1:-1}
|
---|
[363] | 23 | # Shutdown delay is NOT considered idle time, but just a save guard.
|
---|
[362] | 24 | SHUTDOWN_DELAY=${2:-15}
|
---|
| 25 |
|
---|
[363] | 26 |
|
---|
[361] | 27 | # Stored as <epoch> <load>
|
---|
| 28 | DAT_FILE='/tmp/power-saver.dat'
|
---|
| 29 |
|
---|
| 30 | # Current values
|
---|
| 31 | EPOCH=`date "+%s"`
|
---|
| 32 | LOAD_15=`sysctl vm.loadavg | awk '{print $5}'`
|
---|
| 33 |
|
---|
| 34 | # Empty file needs to be created and filled
|
---|
| 35 | echo "$EPOCH $LOAD_15" >> $DAT_FILE || exit 1
|
---|
| 36 |
|
---|
| 37 | # Check if countdown has already been started
|
---|
| 38 | ps -x | grep -q '[0-9] shutdown' && exit 0
|
---|
| 39 |
|
---|
| 40 | # Check if all users are no longer active
|
---|
[362] | 41 | SHORTEST_IDLE=`w -ih | awk -vIDLE_USER=$IDLE_USER '{if (NR == IDLE_USER) print $5}'`
|
---|
[361] | 42 | # Hack to make sure time is always in minutes
|
---|
| 43 | SHORTEST_IDLE_IN_MIN=`echo $SHORTEST_IDLE | awk -F: '{if (NF > 1){print $1 * 60 + $2}else{print $1}}'`
|
---|
| 44 | if [ -z "$SHORTEST_IDLE_IN_MIN" ]; then
|
---|
| 45 | # No users are currently logged in
|
---|
| 46 | continue
|
---|
| 47 | elif [ "$SHORTEST_IDLE_IN_MIN" = "-" ]; then
|
---|
| 48 | # User is still active an minute ago
|
---|
| 49 | exit 0
|
---|
| 50 | elif [ $SHORTEST_IDLE_IN_MIN -le $MAX_IDLE ]; then
|
---|
| 51 | # User is still active less than MAX_IDLE ago
|
---|
| 52 | exit 0
|
---|
| 53 | fi
|
---|
| 54 |
|
---|
| 55 | # Count the amount entries we are current on our way
|
---|
| 56 | IDLE_COUNTS=`awk -vMAX_LOAD=$MAX_LOAD -vMAX_IDLE=$MAX_IDLE -vEPOCH=$EPOCH \
|
---|
[364] | 57 | 'BEGIN{MIN_TIME=EPOCH-MAX_IDLE * 60;s=0}{if ($1 > MIN_TIME && $2 < MAX_LOAD){s += 1}}END{print s}' $DAT_FILE`
|
---|
[361] | 58 |
|
---|
| 59 | # We are idle for over $MAX_IDLE time, starting shutdown
|
---|
[363] | 60 | if [ $IDLE_COUNTS -ge `expr $MAX_IDLE / $CRON_INTERVAL` ]; then
|
---|
| 61 | shutdown -p "+$SHUTDOWN_DELAY" "Cancel: sudo killall -SIGTERM shutdown"
|
---|
[361] | 62 | fi
|
---|