2 hours ago2 hr If you boot Unraid from an internal device rather than a USB flash drive, Dynamix System Autofan can end up seeing no drives at all, and parks your fans at their minimum - which may be slower than the BIOS would have run them. It does this silently: no error, and nothing in syslog, because the "adjusting fan speed" line only prints when the computed speed changes. Why it happensautofan works out which device is the boot flash so it can leave it out of the temperature scan:flash=/dev/$(ls -l /dev/disk/by-label| grep UNRAID | cut -d/ -f3 | cut -c 1-3) DRIVES=$(ls /dev/{[hs]d*[a-z],nvme[0-9]} | grep -v "$flash")That assumes a filesystem label of UNRAID. Booting from NVMe/ZFS gives the boot partition the ZFS pool name as its label instead, so the grep matches nothing, $flash becomes the bare string "/dev/", and grep -v "/dev/" throws away every device in the list.With no drives to read, the highest temperature is 0, which is below your low threshold, so the fan is set to PWM_OFF and held there. How to check if you are affectedls -l /dev/disk/by-label/ | grep -c UNRAID flash=/dev/$(ls -l /dev/disk/by-label| grep UNRAID | cut -d/ -f3 | cut -c 1-3); echo "[$flash]" ls /dev/{[hs]d*[a-z],nvme[0-9]} | grep -v "$flash" | wc -lIf the first is 0, the second prints [/dev/], and the third is 0, that is it. On my machine this took the drive-cage fans from about 490 rpm under the BIOS curve down to about 263 rpm, with the array sitting at 49C. Enabling the plugin made cooling worse than leaving it off. WorkaroundGive autofan the label it is looking for, pointing at the real boot partition. /dev is tmpfs, so recreate it each boot from your go file:boot_part=$(readlink -f /dev/disk/by-label/flash 2>/dev/null) [ -b "$boot_part" ] && ln -sfn "$boot_part" /dev/disk/by-label/UNRAIDSubstitute your own boot pool name for "flash". One side effect on NVMe systems: the lookup keeps only the first 3 characters of the target, so it derives "nvm" and also excludes every /dev/nvme*. That may or may not be what you want - use -e if you need finer control. Suggested fixes1. Guard against an empty drive list. If no temperature can be read from anything, leave fan control alone and log it, rather than driving the fan to minimum. A temperature of 0 means "no data", not "everything is cold". This is also what was asked for in bergware/dynamix issue #63 back in 2022, and a guard there would cover that route to the same outcome.2. Do not depend on the UNRAID label. /boot is already mounted, and the boot partition carries PARTLABEL="Unraid Boot Partition" - either is a more reliable signal. For a ZFS boot pool, zpool list -vHP <pool> gives the backing device. NVMe needs normalising, because the drive list enumerates controllers (/dev/nvme0) while these lookups yield namespaces (nvme0n1).I have a tested patch for both if a maintainer wants it. EnvironmentDynamix System Autofan 2025.11.14, autofan script version 1.7 Unraid Server OS 7.3.2 Boots from NVMe; boot partition nvme0n1p3, ZFS, pool label "flash" 16 SATA HDDs + 3 NVMeA note on where to report this: unraid/dynamix serves the installed .plg but has issues disabled, bergware/dynamix accepts issues but is the pre-migration home (the 2025.11.14 changelog entry reads "Migrate repository to Unraid"), and unraid/webgui accepts issues but does not ship this plugin. Hence posting here.
2 hours ago2 hr Author Here are the changes, against scripts/autofan version 1.7 as shipped in 2025.11.14. Three edits, covering both suggestions above. Please note what has and has not been testedThis is tested on exactly one configuration: NVMe/ZFS boot, 16 SATA HDDs and 3 NVMe, Unraid 7.3.2. There the detection resolves /dev/nvme0 correctly and the boot device is properly excluded, with no UNRAID label present anywhere on the system.The ZFS branch and the NVMe name normalisation are both verified on that machine. The USB-stick fallback path is reasoning rather than testing - I have no USB-boot system to try it against, so that branch in particular deserves a second pair of eyes before anyone relies on it.The normalisation step is worth attention too: the drive list enumerates NVMe controllers (/dev/nvme0) while both lookups yield namespaces (nvme0n1), so without it the boot device is detected correctly and then still not excluded. That cost me a while to spot. 1. Replace the two flash-detection linesReplaces the comment and the flash= line around line 168:# Obtain the base device of the Unraid boot flash, so it can be left out of # the temperature scan. # # Do not rely on a filesystem label of "UNRAID". Unraid 7 can boot from an # internal device rather than a USB stick, in which case the boot partition # carries the ZFS pool name as its label and no UNRAID label exists anywhere. # The old lookup then yielded an empty string, "$flash" became the bare string # "/dev/", and "grep -v" silently discarded *every* drive in the machine. flash= boot_src=$(findmnt -no SOURCE /boot 2>/dev/null) if [[ -n $boot_src ]]; then if [[ -b $boot_src ]]; then # ordinary block device (USB stick or partition) flash=$(lsblk -no PKNAME "$boot_src" 2>/dev/null | head -1) else # ZFS dataset such as "flash/boot": resolve the pool's backing device boot_pool=${boot_src%%/*} boot_dev=$(zpool list -vHP "$boot_pool" 2>/dev/null | awk '$1 ~ /^\/dev\// {print $1; exit}') [[ -n $boot_dev ]] && flash=$(lsblk -no PKNAME "$boot_dev" 2>/dev/null | head -1) fi fi # Fallback: the classic USB stick labelled UNRAID if [[ -z $flash ]]; then flash=$(ls -l /dev/disk/by-label 2>/dev/null | awk '/UNRAID/{print $NF}' | sed 's|.*/||' | sed 's/[0-9]*$//' | head -1) fi if [[ -n $flash ]]; then # The drive list below enumerates NVMe controllers (/dev/nvme0), while the # lookups above yield the namespace (nvme0n1). Normalise so they compare. [[ $flash == nvme*n[0-9]* ]] && flash=${flash%%n[0-9]*} flash="/dev/$flash" else # Never let an unknown boot device become a pattern that matches everything. flash="__autofan_no_boot_device__" echo "$program_name: warning: could not identify the boot device; no drive will be excluded from the temperature scan" | logger -t$program_name fi 2. Add a guard after the drive list is builtGoes immediately after the "for d in $DRIVES" loop that fills HD[]:# If this leaves nothing to measure, the fan must not be touched. A drive list # that came out empty means the configuration or the detection above is wrong, # not that the machine is cold, and driving the fan to its minimum on that # basis can leave the disks with less airflow than the BIOS curve gave them. if [[ ${#HD[@]} -eq 0 ]]; then echo "$program_name: no drives to monitor (check the exclude list); leaving fan control untouched" | logger -t$program_name NO_DRIVES=1 else NO_DRIVES= fi 3. Honour that guard in the main loopGoes just after the existing "Just wait if modules aren’t loaded" check: # Nothing to measure: never drive the fan on a guess. Leave it wherever it # is - the BIOS curve, or whatever set it last - and try again next interval. if [[ -n $NO_DRIVES ]]; then sleep $(($INTERVAL*60)); continue; fiHappy to rework any of it if the approach looks wrong - in particular, someone with a USB-boot system confirming the fallback still behaves would be worth more than anything I can test here.
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.