286 lines
11 KiB
Bash
Executable File
286 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
|
#=======================================================================================
|
|
# Name: autofan
|
|
#=======================================================================================
|
|
# Description:
|
|
#
|
|
# A simple script to check for the highest hard disk temperature and then set the
|
|
# fan to an apropriate speed. Fan needs to be connected to a motherboard with pwm
|
|
# support.
|
|
#
|
|
# How to invoke in your "go" script (copy to /boot/scripts):
|
|
# chmod +x /boot/scripts/fan_speed.sh -- superseeded by Dynamix plugin
|
|
# /boot/fan_speed.sh -- superseeded by Dynamix plugin
|
|
#=======================================================================================
|
|
# Version 1.0 Authored by Aiden
|
|
# Version 1.1 Modified by Dan Stroot to run in a loop. Does not require the user
|
|
# to add this to cron - just start it in your go file.
|
|
# Version 1.2 Modified by Guzzi - removed -d ata to work on sas controllers
|
|
# Version 1.3 Modified by gfjardim - added to dynamix.system.autofan
|
|
# Version 1.4 Modified by Bergware - added additional line parameters
|
|
# start/stop control by Dynamix plugin
|
|
#=======================================================================================
|
|
# Dependencies: grep,awk,smartctl,hdparm
|
|
#=======================================================================================
|
|
version=1.4
|
|
program_name="autofan"
|
|
usage() {
|
|
echo "Usage: $program_name [-t min_temp] [-T max_temp] [-m loop in minutes] [-c controller] [-f fan] [-l low]"
|
|
echo " $program_name -V = print program version "
|
|
echo " $program_name -q = quit the program if it is running"
|
|
echo
|
|
echo " Argument descriptions:"
|
|
echo " -t NN = set the low disk temp, below this temp the fan is off (default=35)"
|
|
echo " -T NN = set the high disk temp, above this temp the fan is 100% (default=45)"
|
|
echo " -c name = specify name of the controller (default=/sys/class/hwmon/hwmon2/pwm1)"
|
|
echo " -f name = specify name of the fan (default=/sys/class/hwmon/hwmon2/fan1_input)"
|
|
echo " -l NN = set value to slow down the fan speed (default=35)"
|
|
echo " -m NN = number of minutes to wait between fan speed changes (default=5)"
|
|
}
|
|
#=======================================================================================
|
|
# USER DEFINED VARIABLES: *MUST* BE SET TO *YOUR* VALUES
|
|
#=======================================================================================
|
|
# Fan device. Depends on *your* system. pwmconfig can help with finding this out.
|
|
# pwm1 is usually the cpu fan. You can "cat /sys/class/hwmon/hwmon1/device/fan4_input"
|
|
# to see the current rpm of the fan. If 0 then fan is off or there is no fan connected
|
|
# or motherboard can't read rpm of fan.
|
|
PWM_CONTROLLER=/sys/class/hwmon/hwmon2/pwm1 # Power (speed) setting
|
|
PWM_FAN=/sys/class/hwmon/hwmon2/fan1_input # Used to track actual rpm values
|
|
|
|
# Temperature boundaries
|
|
TEMP_LOW=35 # Anything this number and below - fan is *off*
|
|
TEMP_HIGH=45 # Anything this number and above - fan is *full*
|
|
|
|
# Fan speed settings. Run pwmconfig (part of the lm_sensors package) to determine
|
|
# what numbers you want to use for your fan pwm settings. Should not need to
|
|
# change the OFF variable, only the LOW and maybe also HIGH to what you desire.
|
|
# Any real number between 0 and 255.
|
|
PWM_OFF=30 # Off Value (note: many PWM fans will not turn off)
|
|
PWM_LOW=35 # Value to make your fan go slow
|
|
PWM_HIGH=255 # Value to make your fan go fast
|
|
|
|
INTERVAL=5 # The default number of minutes to loop
|
|
#=======================================================================================
|
|
# PROGRAM LOGIC - CHANGE AT YOUR PERIL ;)
|
|
#=======================================================================================
|
|
# Get User Input
|
|
while getopts "t:T:m:c:f:l:qhV" opt; do
|
|
case $opt in
|
|
t) TEMP_LOW=$OPTARG ;;
|
|
T) TEMP_HIGH=$OPTARG ;;
|
|
m) INTERVAL=$OPTARG ;;
|
|
c) PWM_CONTROLLER=$OPTARG ;;
|
|
f) PWM_FAN=$OPTARG ;;
|
|
l) PWM_LOW=$OPTARG ;;
|
|
V) echo $program_name version: $version ; exit 0 ;;
|
|
h) usage >&2 ; exit 0 ;;
|
|
q) quit_flag="yes" ;;
|
|
\?) usage >&2 ; exit 0 ;;
|
|
esac
|
|
done
|
|
|
|
show_values() {
|
|
echo TEMP_LOW=$TEMP_LOW
|
|
echo TEMP_HIGH=$TEMP_HIGH
|
|
echo PWM_OFF=$PWM_OFF
|
|
echo PWM_LOW=$PWM_LOW
|
|
echo PWM_HIGH=$PWM_HIGH
|
|
echo INTERVAL=$INTERVAL
|
|
}
|
|
#show_values # uncomment for debugging
|
|
|
|
# validate the fan off temp
|
|
cc="$(echo $TEMP_LOW | sed 's/[0-9]//g')"
|
|
if [[ ! -z $cc ]]; then
|
|
echo "Error: min fan temp must be numeric (whole number, not negative)." >&2
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
# validate the fan high temp
|
|
cc="$(echo $TEMP_HIGH | sed 's/[0-9]//g')"
|
|
if [[ ! -z $cc ]]; then
|
|
echo "Error: max fan temp must be numeric (whole number, not negative)." >&2
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
# validate the minutes
|
|
cc="$(echo $INTERVAL | sed 's/[0-9]//g')"
|
|
if [[ ! -z $cc ]]; then
|
|
echo "Error: minutes must be numeric (whole number, not negative)." >&2
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
# Lockfile processing
|
|
lockfile="/var/run/${program_name}.pid"
|
|
if [[ -f $lockfile ]]; then
|
|
# The file exists so read the PID
|
|
# to see if it is still running
|
|
lock_pid=`head -n 1 "${lockfile}"`
|
|
pid_running=`ps -p "${lock_pid}" | grep ${lock_pid}`
|
|
|
|
if [[ -z $pid_running ]]; then
|
|
if [[ $quit_flag == no ]]; then
|
|
# The process is not running
|
|
# Echo current PID into lock file
|
|
echo $$ > "${lockfile}"
|
|
else
|
|
echo "$program_name ${lock_pid} is not currently running "
|
|
rm "${lockfile}"
|
|
fi
|
|
else
|
|
if [[ $quit_flag == yes ]]; then
|
|
echo killing $program_name process "$lock_pid"
|
|
echo killing $program_name process "$lock_pid" | logger -t$program_name
|
|
kill "$lock_pid"
|
|
rm "${lockfile}"
|
|
exit 0
|
|
else
|
|
echo "$program_name is already running [${lock_pid}]"
|
|
exit 2
|
|
fi
|
|
fi
|
|
else
|
|
if [[ $quit_flag == yes ]]; then
|
|
echo "$program_name not currently running "
|
|
exit 0
|
|
else
|
|
echo $$ > "${lockfile}"
|
|
fi
|
|
fi
|
|
|
|
# Obtain the ID of your flash drive (your flash drive is named "UnRaid" right?)
|
|
flash=/dev/`ls -l /dev/disk/by-label| grep UNRAID | cut -d/ -f3 | cut -c 1-3`
|
|
|
|
# Count the number of drives in your array (ignoring the flash drive we identified)
|
|
NUM_OF_DRIVES=$(ls /dev/[hs]d? | grep -v "$flash" | wc -l)
|
|
|
|
# Identify the drives in your array so we can test their temperature
|
|
COUNT=1
|
|
for d in $(ls /dev/[hs]d? | grep -v "$flash"); do
|
|
HD[$COUNT]=$d
|
|
#echo HDD=${HD[$COUNT]} # Uncomment for debugging
|
|
COUNT=$[$COUNT+1]
|
|
done
|
|
|
|
function_get_highest_hd_temp() {
|
|
HIGHEST_TEMP=0
|
|
for DISK in "${HD[@]}"; do
|
|
SLEEPING=`hdparm -C ${DISK} | grep -c standby`
|
|
if [[ $SLEEPING -eq 0 ]]; then
|
|
CURRENT_TEMP=`smartctl -A ${DISK} | grep -m 1 -i Temperature_Celsius | awk '{print $10}'`
|
|
if [[ $HIGHEST_TEMP -le $CURRENT_TEMP ]]; then
|
|
HIGHEST_TEMP=$CURRENT_TEMP
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
function_get_current_fan_speed() {
|
|
# Function to get current fan values
|
|
CURRENT_FAN_SPEED=`cat $PWM_CONTROLLER`
|
|
CURRENT_FAN_RPM=`cat $PWM_FAN`
|
|
CURRENT_PERCENT_SPEED=$(($(($CURRENT_FAN_SPEED*100))/$PWM_HIGH))
|
|
#echo Current Fan Speed = $CURRENT_FAN_SPEED # Uncomment for debugging
|
|
#echo Current Fan RPM = $CURRENT_FAN_RPM # Uncomment for debugging
|
|
#echo Current Percent Speed = $CURRENT_PERCENT_SPEED # Uncomment for debugging
|
|
if [[ $CURRENT_FAN_SPEED -le $PWM_OFF ]]; then
|
|
CURRENT_OUTPUT="OFF (0% @ 0rpm)"
|
|
#echo Current output = $CURRENT_OUTPUT # Uncomment for debugging
|
|
else
|
|
if [[ $CURRENT_FAN_SPEED -ge $PWM_HIGH ]]; then
|
|
CURRENT_OUTPUT="FULL (100% @ ${CURRENT_FAN_RPM}rpm)"
|
|
#echo Current output = $CURRENT_OUTPUT # Uncomment for debugging
|
|
else
|
|
CURRENT_OUTPUT="$CURRENT_FAN_SPEED (${CURRENT_PERCENT_SPEED}% @ ${CURRENT_FAN_RPM}rpm)"
|
|
#echo Current output = $CURRENT_OUTPUT # Uncomment for debugging
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function_calc_new_fan_speed() {
|
|
# Calculate new fan values based on highest drive temperature
|
|
if [[ $HIGHEST_TEMP -le $TEMP_LOW ]]; then
|
|
ADJUSTED_FAN_SPEED=$PWM_OFF
|
|
ADJUSTED_PERCENT_SPEED=0
|
|
ADJUSTED_OUTPUT="OFF"
|
|
else
|
|
if [[ $HIGHEST_TEMP -ge $TEMP_HIGH ]]; then
|
|
ADJUSTED_FAN_SPEED=$PWM_HIGH
|
|
ADJUSTED_PERCENT_SPEED=100
|
|
ADJUSTED_OUTPUT="FULL"
|
|
else
|
|
ADJUSTED_FAN_SPEED=$(($(($(($HIGHEST_TEMP-$TEMP_LOW))*$FAN_PWM_INCREMENTS))+$PWM_LOW))
|
|
ADJUSTED_PERCENT_SPEED=$(($(($ADJUSTED_FAN_SPEED*100))/$PWM_HIGH))
|
|
ADJUSTED_OUTPUT=$ADJUSTED_FAN_SPEED
|
|
fi
|
|
fi
|
|
#echo Adjusted output = $ADJUSTED_OUTPUT # Uncomment for debugging
|
|
}
|
|
|
|
function_change_fan_speed() {
|
|
# Implemenent fan speed change if neeeded
|
|
if [[ $CURRENT_FAN_SPEED -ne $ADJUSTED_FAN_SPEED ]]; then
|
|
# Enable speed change on fan
|
|
if [[ `cat ${PWM_CONTROLLER}_enable` -ne 1 ]]; then
|
|
echo 1 > "${PWM_CONTROLLER}_enable"
|
|
fi
|
|
# set fan to new value
|
|
echo $ADJUSTED_FAN_SPEED > $PWM_CONTROLLER
|
|
sleep 5
|
|
# Get new rpm value
|
|
ADJUSTED_FAN_RPM=`cat $PWM_FAN`
|
|
ADJUSTED_OUTPUT="${ADJUSTED_OUTPUT} (${ADJUSTED_PERCENT_SPEED}% @ ${ADJUSTED_FAN_RPM}rpm)"
|
|
# Output the change
|
|
echo "$program_name: Highest disk temp is ${HIGHEST_TEMP}°C, adjusting fan speed from: $CURRENT_OUTPUT to: $ADJUSTED_OUTPUT"
|
|
echo "Highest disk temp is ${HIGHEST_TEMP}°C, adjusting fan speed from: $CURRENT_OUTPUT to: $ADJUSTED_OUTPUT" | logger -t$program_name
|
|
fi
|
|
}
|
|
|
|
# Main Loop
|
|
while [[ -f $lockfile ]]; do
|
|
# Just wait if modules aren't loaded
|
|
if [[ ! -f $PWM_FAN || ! -f $PWM_CONTROLLER ]]; then
|
|
sleep $(($INTERVAL*60));
|
|
continue;
|
|
fi
|
|
|
|
# Set PWM_OFF
|
|
PWM_OFF=$(($PWM_LOW-5)) # Off Value (note: many PWM fans will not turn off)
|
|
|
|
# Disable fan mininum RPM
|
|
FAN_RPM_MIN=$(echo ${PWM_FAN} | cut -d"_" -f1)"_min"
|
|
if [[ $(cat $FAN_RPM_MIN) -ne 0 ]]; then
|
|
echo 0 > $FAN_RPM_MIN
|
|
fi
|
|
|
|
# Calculate size of increments.
|
|
FAN_TEMP_INCREMENTS=$(($TEMP_HIGH-$TEMP_LOW))
|
|
FAN_PWM_INCREMENTS=$(($(($PWM_HIGH-$PWM_LOW))/$FAN_TEMP_INCREMENTS))
|
|
|
|
# Get highest drive temperature
|
|
function_get_highest_hd_temp
|
|
|
|
# Get current fan speed
|
|
function_get_current_fan_speed
|
|
|
|
# Calculate new fan speed
|
|
function_calc_new_fan_speed
|
|
|
|
# Change fan speed if necessary
|
|
function_change_fan_speed
|
|
|
|
#echo Sleeping for $INTERVAL minutes # uncomment for debugging
|
|
sleep $(($INTERVAL*60))
|
|
done &
|
|
|
|
# while loop was put into background, now disown it so it will continue to run when you log off.
|
|
# to get it to stop, type: rm /var/lock/fan_speed.LCK
|
|
background_pid=$!
|
|
echo $background_pid > "${lockfile}"
|
|
echo "$program_name process ID $background_pid started, To terminate it, type: $program_name -q" >&2
|
|
echo "$program_name process ID $background_pid started, To terminate it, type: $program_name -q" | logger -t$program_name
|
|
disown %%
|