Have been working on a custom script to manage fan control within my external disk only 24 bay chassis using drive temps within unraid.
Didnt like the auto fan control plugin or another custom script I found as using smart reports caused drives to spinup unnecessarily.
Additionally as using 3x 3A 120mm server fans both noise and power consumption were issues needing bringing in check.
So I have parsed the disks.ini file to check temps reported by UNRAID itself.
I wanted to go this route to remove any unnecessary additional scripts/dockers/plugins, just simple check unraid reported temps and adjust fans accordingly.
Its a little crude right now but seems to be working, after a few hours of testing.
Feel free to offer any comments/suggestions but please be gentle as was my first attempt at bash scripting.
Can probably reduce the pwm level steps, would like to implement basic logging and needs bit more testing but its a good start.
Few ideas/lines were borrowed from another script I found online but struggling to find right now to credit.
#!/bin/bash
##VARIABLES
MIN_PWM=40
LOW_PWM=50
HIGH_PWM=180
MAX_PWM=220
LOW_TEMP=25
HIGH_TEMP=35
MAX_TEMP=39
ARRAY_FAN=/sys/class/hwmon/hwmon2/pwm3
##Disk Types Checked (0 disabled, 1 enabled)
declare -A diskTypesChecked
diskTypesChecked[Parity]=1
diskTypesChecked[Data]=1
diskTypesChecked[Cache]=0
diskTypesChecked[Flash]=0
##Excluded Disks (name as in disk.ini)
excludedDisks=(nvme,cache,cache2,flash)
##Variables
isNumber='^[0-9]+$'
##GET LIST OF ARRAY DISKS
declare -a fullDiskList
while IFS='= ' read var val
do
if [[ $var == \[*] ]]
then
section=${var:2:-2}
fullDiskList+=($section)
eval declare -A ${section}_data
elif [[ $val ]]
then
eval ${section}_data[$var]=$val
fi
done < /var/local/emhttp/disks.ini
##filter out excluded disks and disk types
declare -a diskList
for disk in "${fullDiskList[@]}"
do
diskName=${disk}_data[name]
diskType=${disk}_data[type]
diskId=${disk}_data[id]
diskTypeChecked=${diskTypesChecked[${!diskType}]}
if [[ "${!diskId}" == "" ]] ##ignore unassigned slots
then
: ##dont check
elif [[ "${diskName}" == "${excludedDisks[*]}" ]] ##needs improvement
then
: ##dont check
elif (( ${diskTypeChecked} == 0 ))
then
: ##dont check
else
diskList+=($disk)
fi
done
##CHECK DISKS
declare -A diskState
declare -A diskTemp
maxTempC=0
maxTempDisk=null
activeDisks=0
for disk in "${diskList[@]}"
do
##check disk state
eval thisDiskStateVal=${disk}_data[spundown]
if (( ${thisDiskStateVal} == 1 ))
then
thisDiskState=spundown
diskState[${disk}]=spundown
else
thisDiskState=spunup
diskState[${disk}]=spunup
activeDisks=$((activeDisks+1))
fi
##check disk temp
thisDiskTemp=${disk}_data[temp]
if [[ "$thisDiskState" == "spunup" ]]
then
if [[ "${!thisDiskTemp}" =~ $isNumber ]]
then
diskTemp[${disk}]=${!thisDiskTemp}
if (( "${!thisDiskTemp}" > "$maxTempC" ))
then
maxTempC=${!thisDiskTemp}
maxTempDisk=$disk
fi
else
diskTemp[$disk]=unknown
fi
else
diskTemp[$disk]=na
fi
done
echo Hottest Disk is $maxTempDisk at $maxTempC C
##calculate PWM
##maxTempC=26 ##overide temp for manual control
# Linear PWM Logic Variables - do not modify
NUM_STEPS=$((HIGH_TEMP - LOW_TEMP - 1))
PWM_INCREMENT=$(( (HIGH_PWM - LOW_PWM) / NUM_STEPS))
if (( $activeDisks == 0 ))
then
##all disks spun down
echo All drives are idle/spundown, setting fans to minimum.
FAN_PWM=$MIN_PWM
elif (( $maxTempC <= $LOW_TEMP ))
then
##if hottest drive below low
echo $maxTempC C is below low temp of $LOW_TEMP C, setting fans to minimum.
FAN_PWM=$MIN_PWM
elif (( $maxTempC > $LOW_TEMP && $maxTempC <= $HIGH_TEMP ))
then
##if hottest drive above low but below high
echo $maxTempC C is above low temp of $LOW_TEMP C but below high temp of $HIGH_TEMP C, setting fans to ...
FAN_PWM=$(( ((maxTempC - LOW_TEMP - 1) * PWM_INCREMENT) + MIN_PWM ))
elif (( $maxTempC > $HIGH_TEMP && $maxTempC <= $MAX_TEMP ))
then
##if hottest drive above high but below max
echo $maxTempC C is above high temp of $HIGH_TEMP C but below max temp of $MAX_TEMP C, setting fans to ...
FAN_PWM=$MAX_PWM
elif (( $maxTempC > $MAX_TEMP ))
then
##if hottest drive exceeds max temp
##pause parity/alert
echo $maxTempC C is above max temp of $MAX_TEMP C, setting fans to full and ...
FAN_PWM=255
else
##if all else fails - full power fans
echo undefined outcome, setting fans to full and ...
FAN_PWM=255
fi
echo $FAN_PWM > $ARRAY_FAN
echo Fan PWM set to $FAN_PWM
#for key in "${!diskList[@]}"
#do
# echo -n "key : $key, "
# echo "value: ${diskList[$key]}"
#done
#
#for key in "${!diskTemp[@]}"
#do
# echo -n "key : $key, "
# echo "value: ${diskTemp[$key]}"
#done
#param=temperature
#echo ${!parity_data[@]}
#echo ${!disk2_data[@]}
#echo \*