Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
lightsout for linux (suspend when no network activity for 1 hour)
#!/bin/bash
########################################################################
# LIGHTS OUT FOR LINUX (lofl) #
# This script suspends the computer if it's idle for a given period of #
# time. It monitors network activity, logged on users and CPU load. #
########################################################################
# maximum packet count per minute – usually not more than 12-15
net_threshold=12
# maximum CPU load
load_threshold=0.4
# maximum IDLE time in minutes
time_threshold=60
# network interface to watch
interface=eno1
### DO NOT CHANGE ANYTHING BELOW THIS LINE #############################
# TODO: calculate $net_threshold if not set
# store user count and load in variables
system_up=$(uptime)
system_users=$(echo "$system_up" | perl -ne "print for /([0-9]+)\suser/")
system_load=$(echo "$system_up" | perl -ne "print for /([0-9]+\,[0-9]{2})$/" | sed "s/,/./")
# tell the user
printf "Logged in users:\t$system_users\n"
printf "Load avg (15min):\t$system_load (max $load_threshold)\n"
# create a temporary file to store the network packet count across calls
countfile="/tmp/lightsout_${interface}_count"
printf "Interface:\t\t$interface\n"
if [[ -f $countfile ]]
then
changed=$(date -r $countfile +%s)
printf "Last record:\t\t$(date -d @"$changed")\n"
else
printf "0" > $countfile
fi
# see how many network packets were sent over the given interface
packet_sent=$(cat /sys/class/net/$interface/statistics/tx_packets)
# calculate the difference to the last call of the script
let "packet_difference=$packet_sent-$(cat $countfile)"
let "net_threshold *= $time_threshold"
# tell the user how many packets were sent
printf "Network packets sent:\t$packet_sent (diff: $packet_difference/$net_threshold)\n"
# check if the packet count exceeds the threshold set by the user
if (( "$packet_difference" > "$net_threshold" ));
then
printf "resetting packet count...\n"
printf "$packet_sent" > $countfile
else
let "datediff = $(date +%s) - $changed"
let "time_threshold *= 60"
# tell the user the assumed IDLE time
printf "IDLE seconds:\t\t$datediff/$time_threshold\n"
if (( "$datediff" > "$time_threshold" ));
then
# are users still logged in?
if (( "$system_users" > "0" ));
then
printf "not suspending because users are logged in.\n";
else
# is the CPU occupied?
if [[ $(echo "$system_load>$load_threshold" | bc) -eq 1 ]];
then
printf "not suspending due to CPU load.\n";
else
# reset packet counter and suspend
printf 0 > $countfile
printf "suspending...\n"
systemctl suspend
fi
fi
fi
fi
@krbvroc1

This comment has been minimized.

Copy link

@krbvroc1 krbvroc1 commented Nov 13, 2017

@n1trux -
Your system load parsing does not work on my Centos 7
(my uptime output looks as follows)
19:58:11 up 2:49, 7 users, load average: 0.49, 0.48, 0.55

Here is the code I used which should be more portable across distributions:
system_load=$(cut -d ' ' -f 3 </proc/loadavg)

And for system_users you can simplify to:
system_users=$(w -h | wc -l)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment