Puts QNAP NAS to sleep if idle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
SUSPENDTHRESHOLD=1800 | |
LOADTHRESHOLD=1.7 | |
PACKETSTHRESHOLD=40 | |
NFS_PORT=2049 | |
SMB_PORT=445 | |
NETWORKINTERFACE=bond0 | |
DRY_RUN=false | |
# Color escape sequences | |
RED='\033[0;31m' | |
NC='\033[0m' # No Color | |
check_load_threshold() { | |
local load_name=$1 | |
local load_value=$2 | |
local threshold=$3 | |
# Use awk for decimal comparisons since load average values are in decimal format | |
if awk -v load="$load_value" -v threshold="$threshold" 'BEGIN { exit !(load < threshold) }'; then | |
return 0 # Load condition is below threshold, indicating success | |
else | |
echo "Load condition failed for ${load_name}: ${load_value} >= ${threshold}" | |
return 1 # Load condition exceeds threshold, indicating failure | |
fi | |
} | |
check_load_thresholds() { | |
echo "Checking load thresholds..." | |
local LOAD=$(cat /proc/loadavg) | |
local load_avg_1min=$(echo "$LOAD" | awk '{printf "%.2f", $1}') | |
local load_avg_5min=$(echo "$LOAD" | awk '{printf "%.2f", $2}') | |
local load_avg_15min=$(echo "$LOAD" | awk '{printf "%.2f", $3}') | |
echo "Load Average (1min/5min/15min): $load_avg_1min $load_avg_5min $load_avg_15min" | |
failed_conditions=() | |
if ! check_load_threshold "1-minute Load Average" "$load_avg_1min" "$LOADTHRESHOLD"; then | |
failed_conditions+=("1-minute Load Average") | |
fi | |
if ! check_load_threshold "5-minute Load Average" "$load_avg_5min" "$LOADTHRESHOLD"; then | |
failed_conditions+=("5-minute Load Average") | |
fi | |
if ! check_load_threshold "15-minute Load Average" "$load_avg_15min" "$LOADTHRESHOLD"; then | |
failed_conditions+=("15-minute Load Average") | |
fi | |
if [ ${#failed_conditions[@]} -eq 0 ]; then | |
return 0 # Success: All load conditions are below threshold | |
else | |
echo "Load condition(s) failed." | |
return 1 # Failure: One or more load conditions exceed threshold | |
fi | |
} | |
check_clients_connected() { | |
local port=$1 | |
echo -n "Checking clients connected on port ${port}... " | |
local connected_clients=$(netstat -an | grep ":${port}" | grep "ESTABLISHED" | wc -l) | |
echo "$connected_clients" | |
if [ "$connected_clients" -ge 1 ]; then | |
echo "Multiple clients connected to port ${port}: $connected_clients" | |
return 1 # failure | |
else | |
return 0 # success | |
fi | |
} | |
check_packets_threshold() { | |
echo -n "Checking for average network utilisation... " | |
local PACKETS=$(/opt/bin/vnstat -tr 180 -s -i "$NETWORKINTERFACE" | awk '$1 ~ /(r|t)x/ {sum+= $4} END {print sum}') | |
echo "${PACKETS} packets" | |
if [ "$PACKETS" -lt "$PACKETSTHRESHOLD" ]; then | |
echo "Packet condition passed." | |
return 0 # success | |
else | |
echo "Packet condition failed." | |
return 1 # failure | |
fi | |
} | |
suspend() { | |
echo "Suspending" | |
echo "mem" > /sys/power/state | |
} | |
check_time_since_suspend() { | |
echo "Checking time since last suspension..." | |
local suspend_threshold=$1 | |
NOW=$(date +%s) | |
LASTSUSPENDDATE=$(cat /mnt/HDA_ROOT/.logs/kmsg | grep "PM: suspend exit" | tail -n1 | awk '{print $1, $2, $3}') | |
LASTSUSPENDUNIX=$(date -d "$LASTSUSPENDDATE" +%s) | |
TIMESINCESUSPEND=$(dc $NOW $LASTSUSPENDUNIX - p) | |
if [ -z "$TIMESINCESUSPEND" ]; then | |
TIMESINCESUSPEND=0 | |
fi | |
echo "Suspended $TIMESINCESUSPEND seconds ago" | |
if [ "$TIMESINCESUSPEND" -gt "$suspend_threshold" ]; then | |
return 0 # success | |
else | |
echo "Time since last suspend is less than the threshold." | |
return 1 # failure | |
fi | |
} | |
# Process command-line options | |
while getopts ":d" opt; do | |
case $opt in | |
d) # Option '-d' is specified, indicating dry-run mode | |
DRY_RUN=true | |
;; | |
\?) # Invalid option encountered | |
echo -e "${RED}Invalid option: -$OPTARG${NC}" >&2 | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND - 1)) # Shifts the positional parameters to exclude processed options | |
# Perform all the checks, but skip suspension if any check fails | |
all_checks_pass=true | |
check_time_since_suspend "$SUSPENDTHRESHOLD" || { echo -e "${RED}Time since last suspend is less than the threshold.${NC}"; all_checks_pass=false; } | |
check_load_thresholds || { echo -e "${RED}Load condition(s) failed.${NC}"; all_checks_pass=false; } | |
check_clients_connected "$SMB_PORT" || { echo -e "${RED}Multiple clients connected to port ${SMB_PORT}.${NC}"; all_checks_pass=false; } | |
check_clients_connected "$NFS_PORT" || { echo -e "${RED}Multiple clients connected to port ${NFS_PORT}.${NC}"; all_checks_pass=false; } | |
check_packets_threshold || { echo -e "${RED}Packet condition failed.${NC}"; all_checks_pass=false; } | |
# Check if all checks passed | |
if [ "$all_checks_pass" = true ]; then | |
if [ "$DRY_RUN" = true ]; then | |
echo "Performing dry-run (no actual suspension)" | |
else | |
suspend | |
fi | |
else | |
echo "${RED}One or more conditions failed. Skipping suspension.${NC}" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment