Joseph Trice-Rolph Posted October 6, 2021 Share Posted October 6, 2021 (edited) 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 \* Edited October 6, 2021 by Joseph Trice-Rolph Quote Link to comment
doobyns Posted March 26, 2022 Share Posted March 26, 2022 very interesting, can you tell us how to use this script ? with User Scripts ? at the startup of array ? at schaduled time ? Quote Link to comment
eatoff Posted August 23, 2022 Share Posted August 23, 2022 On 10/6/2021 at 9:28 AM, Joseph Trice-Rolph said: 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. This is a great script, I wish this had been around when i was looking earlier. I was using this one, but found that all drives would be spun up just to check the temperature. This one here - Another request that feel free to ignore, but would be to be able to set an additional temperature monitor and desired temperature range. As in a motherboard temperature, and be able to spin fans based on MB temp or HDD temp, whichever is higher in its range. Quote Link to comment
ProphetSe7en Posted October 28, 2022 Share Posted October 28, 2022 So how can I add all my array fans to this script? I have 4 fans, but the script only list one ARRAY_FAN=/sys/class/hwmon/hwmon2/pwm3 So I want to add pwm3-6 to the ARRAY_FAN variable, and not only pwm3 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.