lm-sensors + fancontrol configurés sur un NAS Atom Debian 12 pour piloter le ventilateur via le Super I/O ITE IT8721F. Config dans /etc/fancontrol qui hardcode des paths comme hwmon1/pwm1, hwmon0/temp2_input. Tout marche.
Reboot. fancontrol.service en failed. Ventilo bloqué à pleine vitesse (mode safety du chip).
$ journalctl -u fancontrol
fancontrol[1070]: Device path of hwmon0 has changed
fancontrol[1070]: Device name of hwmon1 has changed
fancontrol[1070]: Configuration appears to be outdated, please run pwmconfig again
Diagnostic
$ for h in /sys/class/hwmon/hwmon*; do echo "$h: $(cat $h/name)"; done
/sys/class/hwmon/hwmon0: it8721
/sys/class/hwmon/hwmon1: coretemp
L’ordre hwmon0 / hwmon1 a swappé entre les deux boots. La config hardcode hwmon1/pwm1 qui pointe maintenant sur le coretemp — pas de pwm là-bas → fancontrol détecte le mismatch via DEVPATH/DEVNAME et refuse de tourner.
Le hwmonN est attribué dans l’ordre où les drivers s’enregistrent au kernel. Cet ordre dépend de modules.dep, de la parallélisation systemd, de l’ACPI scan. Rien ne garantit la stabilité.
DEVPATH=hwmon0=devices/platform/coretemp.0 semble dire « trouve le coretemp et appelle-le hwmon0 ». En réalité c’est un mécanisme de validation, pas de résolution. fancontrol vérifie que hwmon0 correspond au coretemp ; si non → outdated, exit 1.
Fix : régénérer le mapping à chaque boot
Petit script qui détecte les hwmon par name (toujours stable), pas par N :
#!/bin/bash
# /usr/local/sbin/regen-fancontrol
for h in /sys/class/hwmon/hwmon*; do
case "$(cat $h/name)" in
it8721) IT_HW=$(basename $h); IT_PATH=$(readlink -f $h | sed 's|/sys/||;s|/hwmon/.*||') ;;
coretemp) C_HW=$(basename $h); C_PATH=$(readlink -f $h | sed 's|/sys/||;s|/hwmon/.*||') ;;
esac
done
cat > /etc/fancontrol <<EOF
DEVPATH=$C_HW=$C_PATH $IT_HW=$IT_PATH
DEVNAME=$C_HW=coretemp $IT_HW=it8721
FCTEMPS=$IT_HW/pwm1=$C_HW/temp2_input $IT_HW/pwm1=$IT_HW/temp1_input
FCFANS=$IT_HW/pwm1=$IT_HW/fan1_input
MINTEMP=$IT_HW/pwm1=70
MAXTEMP=$IT_HW/pwm1=80
MINPWM=$IT_HW/pwm1=50
MINSTOP=$IT_HW/pwm1=50
MINSTART=$IT_HW/pwm1=80
INTERVAL=10
EOF
Hook avant le démarrage du service via un drop-in systemd :
# /etc/systemd/system/fancontrol.service.d/regen.conf
[Service]
ExecStartPre=/usr/local/sbin/regen-fancontrol
Au boot, peu importe l’ordre des hwmon, la config est cohérente.
Lessons learned
/sys/class/hwmon/hwmonNn’est PAS stable — c’est un artefact d’enregistrement runtime.- DEVPATH/DEVNAME valident, ils ne résolvent pas.
- Identifier les chips par
nameest la seule approche stable. L’équivalent du UUID pour les filesystems. ExecStartPrerégénère la config volatile avant qu’un service la consomme.