Diese Steuerung funktioniert, ist aber eigentlich veraltet, da nun das fanctl existiert. Hierzu gibt es einen entsprechenden Beitrag. Leider schaltet sich der interne Lüfter des CH3SNAS trotz des Energiemanagements der Festplatten nicht ab und läuft daher stetig leise vor sich hin. Dieses “Feature” (“It’s not a Bug, it’s a Feature”) bringt mehrere Dinge mit sich. Zum einen habe ich dadurch eine stetige Lärmquelle in meinem Zimmer, die Nachts doch ein wenig nerven kann. Zum anderen spart die Abschaltung des Lüfters wieder einige Watt. Desweiteren wird so die Lebensdauer des Lüfters deutlich erhöht.

Diese Anleitung bedingt, dass das fun_plug (Artikel) korrekt installiert wurde. Zudem weise ich darauf hin, dass ich nicht für eventuelle Schäden, Datenverluste oder andere Probleme haften werden. Das Verwenden dieses Artikels geschieht auf eigene Gefahr! Bitte beachtet meine Hinweise zu Release Candidates der Firmware 1.04!

Zur Erklärung des Codes der Lüftersteuerung: Zunächst wird der alte Lüftercontroller gekillt, da dieser sonst dazwischenfunken würde. Darunter werden die Genzwerte konfiguriert. Mein Lüfter schaltet sich ab einer Temperatur von 96 Grad Fahrenheit ein und dreht dann mit 2700rpm. Im Bereich bis 110 Grad Fahrenheit dreht dann der Lüfter im Geschwindigkeitsbereich von 2700rpm bis 3500rpm (Maximal sind 6000rpm möglich). Wenn die Festplatten sich ausschalten, wird geprüft ob das NAS bereits unter der Temperatur1 liegt (d.h. hier unter 96°F). Wenn ja, wird die Idle-Drehzahl gesetzt, die 0 ist, womit der Lüfter stehen bleibt. Wenn nein, dann dreht der Lüfter auf RPM1 (hier 2700rpm) weiter, bis das NAS kühl genug ist. Eine Alternative, die nicht Festplattenabhängig ist, findet sich unter den folgenden drei Skripten.

Details zur Einbindung und Installation finden sich unter den Skripten.

Code für eine Festplatte OHNE LOGGING

Das Skript wurde auf eine Festplatte (hier “HD1”, für “HD0” einfach die Bezeichnungen ändern) ausgerichtet, es werden keine Aktivitäten geloggt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/bin/sh
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/mnt/HD_a2/fun_plug.d/bin/
# Converts Fahrenheit to Celcius
f2c() {
 /bin/echo `expr \( \( $1 - 32 \) \* 10 + 9 \) \/ 18`
}
# Converts Celcius to Fahrenheit
c2f() {
 /bin/echo `expr \( $1 \* 9 \) \/ 5 \+ 32`
}
# Kill the old fan controller
PID=$(/bin/pidof fancontrol)
if [ -n "$PID" ]
then
 kill -9 $PID
fi
update_interval=60
#T1 and T2 in fahrenheit - convert if necessary using c2f function
T1=96
T2=110
IDLERPM=0
RPM1=2700
RPM2=3500
while [ 1 ]
do
 #Find out current temperature
 T=`temperature g 0`
 T=${T##*=}
 C=`temperature g 0 | grep -i -c centigrade `
# Convert to Fahrenheit if output is in Celcius
if [ $C -gt 0 ]
then
 C=$T
 F=$(c2f $C)
 T=$F
else
 F=$T
 C=$(f2c $F)
fi
 #Search dmesg for hard drive messages
 DRIVE1_dmesg=`/bin/dmesg | /bin/grep HD1 | /bin/tail -1`
 DRIVE1_awake=`/bin/dmesg | /bin/grep HD1 | /bin/tail -1 | /bin/grep awake`
 # Calculate new fanspeed, depending on if drive is awake or not
 if [ -n "${DRIVE1_dmesg}" ]; then
 # True if dmesg contains status for drive
 if [ -n "${DRIVE1_awake}" ]; then
 # True if any of the drives are awake, keep fan running
 newRPM=`expr \( \( $T2 \< $F \) \* $RPM2 \) \| \( \( $RPM1 + \( $RPM2 - $RPM1 \) \* \( $F - $T1 \) \/ \( $T2 - $T1 \) \) \& \( $F \>= $T1 \) \)`
 else
 # None of the drives is awake, now check if Temperature is above $T1
 if [ $T -gt $T1 ]; then
 #Keep the fan running until the NAS has cooled down
 newRPM=$RPM1
 else
 #set speed to IDLE speed
 newRPM=$IDLERPM
 fi
 fi
 else
 # dmesg does not yet contain the status the drive
 # (it has probably never powered down), keep fan running
 newRPM=`expr \( \( $T2 \< $F \) \* $RPM2 \) \| \( \( $RPM1 + \( $RPM2 - $RPM1 \) \* \( $F - $T1 \) \/ \( $T2 - $T1 \) \) \& \( $F \>= $T1 \) \)`
 fi
 # Set the new fan speed
 fanspeed w $newRPM
 # Write some more to logfile
 # Wait for next cycle
 /bin/sleep $update_interval
done

Code für 2 Festplatten MIT LOGGING

Das Skript wurde auf auf beide Festplatten ausgerichtet, es werden alle Aktivitäten geloggt und der aktuelle Status hinterlegt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/bin/sh
PATH=/usr/bin:/bin:/usr/sbin:/sbin
# Converts Fahrenheit to Celcius
f2c() {
 /bin/echo `expr \( \( $1 - 32 \) \* 10 + 9 \) \/ 18`
}
# Converts Celcius to Fahrenheit
c2f() {
 /bin/echo `expr \( $1 \* 9 \) \/ 5 \+ 32`
}
# Kill the old fan controller
PID=$(/bin/pidof fancontrol)
if [ -n "$PID" ]
 then
 kill -9 $PID
fi
update_interval=60
#T1 and T2 in fahrenheit - convert if necessary using c2f function
T1=96
T2=110
IDLERPM=0
RPM1=2700
RPM2=3500
LOGDIR=/log
LOGFILE=${LOGDIR}/fan.txt
STATFILE=${LOGDIR}/fanstat.txt
mkdir -p ${LOGDIR}
while [ 1 ]
do
 #Find out current temperature
 T=`temperature g 0`
 T=${T##*=}
 C=`temperature g 0 | grep -i -c centigrade `
# Convert to Fahrenheit if output is in Celcius
if [ $C -gt 0 ]
then
 C=$T
 F=$(c2f $C)
 T=$F
else
 F=$T
 C=$(f2c $F)
fi
#Search dmesg for hard drive messages
DRIVE0_dmesg=`/bin/dmesg | /bin/grep HD0 | /bin/tail -1`
DRIVE1_dmesg=`/bin/dmesg | /bin/grep HD1 | /bin/tail -1`
DRIVE0_awake=`/bin/dmesg | /bin/grep HD0 | /bin/tail -1 | /bin/grep awake`
DRIVE1_awake=`/bin/dmesg | /bin/grep HD1 | /bin/tail -1 | /bin/grep awake`
# Write some info to logfile
/bin/echo "###############################################################"> $LOGFILE
/bin/echo `date`>> $LOGFILE
/bin/echo "Temp in Fahrenheit: $F" >> $LOGFILE
/bin/echo "Temp in Celcius: $C" >> $LOGFILE
# Calculate new fanspeed, depending on if drives are awake or not
if [ -n "${DRIVE0_dmesg}" ] && [ -n "${DRIVE1_dmesg}" ]; then
# True if dmesg contains status for both drives
if [ -n "${DRIVE0_awake}" ] || [ -n "${DRIVE1_awake}" ]; then
# True if any of the drives are awake, keep fan running
newRPM=`expr \( \( $T2 \< $F \) \* $RPM2 \) \| \( \( $RPM1 + \( $RPM2 - $RPM1 \) \* \( $F - $T1 \) \/ \( $T2 - $T1 \) \) \& \( $F \>= $T1 \) \)`
if [ -n "${DRIVE0_awake}" ]; then
# True if the first drive is awake
/bin/echo "The first drive is awake">> $LOGFILE
else
/bin/echo "The first drive is hibernating">> $LOGFILE
fi
if [ -n "${DRIVE1_awake}" ]; then
# True if the second drive is awake
/bin/echo "The second drive is awake">> $LOGFILE
else
/bin/echo "The second drive is hibernating">> $LOGFILE
fi
else
 # None of the drives is awake, now check if Temperature is above $T1
 if [ $T -gt $T1 ]; then
 #Keep the fan running until the NAS has cooled down
 newRPM=$RPM1
 /bin/echo "Both drives are hibernating. Temperature still to high to switch fan off">> $LOGFILE
 else
 #set speed to IDLE speed
 newRPM=$IDLERPM
 /bin/echo "Both drives are hibernating. Setting IDLE speed for fan">> $LOGFILE
 fi
fi
else
# dmesg does not yet contain the status for both drives
# (at least one of the drives has never been powered down), keep fan running
newRPM=`expr \( \( $T2 \< $F \) \* $RPM2 \) \| \( \( $RPM1 + \( $RPM2 - $RPM1 \) \* \( $F - $T1 \) \/ \( $T2 - $T1 \) \) \& \( $F \>= $T1 \) \)`
/bin/echo "Could not determine status for both drives, one of them is probably awake">> $LOGFILE
fi
/bin/echo `date` $C $F `fanspeed g` $newRPM>> $STATFILE
# Set the new fan speed
fanspeed w $newRPM
# Write some more to logfile
/bin/echo "Fanspeed: " $newRPM "rpm">> $LOGFILE
/bin/echo "###############################################################">> $LOGFILE
# Wait for next cycle
/bin/sleep $update_interval
done

Code für 2 Festplatten OHNE LOGGING

Das Skript wurde auf auf beide Festplatten ausgerichtet, es werden keine Aktivitäten geloggt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/bin/sh
PATH=/usr/bin:/bin:/usr/sbin:/sbin
# Converts Fahrenheit to Celcius
f2c() {
 /bin/echo `expr \( \( $1 - 32 \) \* 10 + 9 \) \/ 18`
}
# Converts Celcius to Fahrenheit
c2f() {
 /bin/echo `expr \( $1 \* 9 \) \/ 5 \+ 32`
}
# Kill the old fan controller
PID=$(/bin/pidof fancontrol)
if [ -n "$PID" ]
 then
 kill -9 $PID
fi
update_interval=60
#T1 and T2 in fahrenheit - convert if necessary using c2f function
T1=96
T2=110
IDLERPM=0
RPM1=2700
RPM2=3500
while [ 1 ]
do
 #Find out current temperature
 T=`temperature g 0`
 T=${T##*=}
 C=`temperature g 0 | grep -i -c centigrade `
# Convert to Fahrenheit if output is in Celcius
if [ $C -gt 0 ]
then
 C=$T
 F=$(c2f $C)
 T=$F
else
 F=$T
 C=$(f2c $F)
fi
#Search dmesg for hard drive messages
DRIVE0_dmesg=`/bin/dmesg | /bin/grep HD0 | /bin/tail -1`
DRIVE1_dmesg=`/bin/dmesg | /bin/grep HD1 | /bin/tail -1`
DRIVE0_awake=`/bin/dmesg | /bin/grep HD0 | /bin/tail -1 | /bin/grep awake`
DRIVE1_awake=`/bin/dmesg | /bin/grep HD1 | /bin/tail -1 | /bin/grep awake`
# Calculate new fanspeed, depending on if drives are awake or not
if [ -n "${DRIVE0_dmesg}" ] && [ -n "${DRIVE1_dmesg}" ]; then
# True if dmesg contains status for both drives
if [ -n "${DRIVE0_awake}" ] || [ -n "${DRIVE1_awake}" ]; then
# True if any of the drives are awake, keep fan running
newRPM=`expr \( \( $T2 \< $F \) \* $RPM2 \) \| \( \( $RPM1 + \( $RPM2 - $RPM1 \) \* \( $F - $T1 \) \/ \( $T2 - $T1 \) \) \& \( $F \>= $T1 \) \)`
else
 # None of the drives is awake, now check if Temperature is above $T1
 if [ $T -gt $T1 ]; then
 #Keep the fan running until the NAS has cooled down
 newRPM=$RPM1
 else
 #set speed to IDLE speed
 newRPM=$IDLERPM
 fi
fi
else
# dmesg does not yet contain the status for both drives
# (at least one of the drives has never been powered down), keep fan running
newRPM=`expr \( \( $T2 \< $F \) \* $RPM2 \) \| \( \( $RPM1 + \( $RPM2 - $RPM1 \) \* \( $F - $T1 \) \/ \( $T2 - $T1 \) \) \& \( $F \>= $T1 \) \)`
fi
# Set the new fan speed
fanspeed w $newRPM
# Wait for next cycle
/bin/sleep $update_interval
done

Leider funktionieren die Lüftersteuerungen bei einem RAID-System wohl nicht, da es keine Meldungen über die Abschaltung der Festplatten gibt (Ich fahre leider kein RAID, daher kann ich das noch nicht beurteilen). Ich habe daher eine zusätzliche Lüftersteuerung entwickelt, die den Lüfter unterhalb einer bestimmten Systemtemperatur abschaltet. Diese habe ich momentan auf 30°C festgesetzt. Darüber hinaus dreht der Lüfter mit 2700rpm bis 3500rpm (je nach Temperatur).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/bin/sh
PATH=/usr/bin:/bin:/usr/sbin:/sbin

# Converts Fahrenheit to Celcius
f2c() {
 /bin/echo $(( (($1 - 32) * 10 + 9) / 18 ))
}

# Converts Celcius to Fahrenheit
c2f() {
 /bin/echo $(( ($1 * 9) / 5 + 32 ))
}

# Kill the old fan controller
PID=$(/bin/pidof fancontrol)
if [ -n "$PID" ]
 then
 kill -9 $PID
fi

# Checking interval in seconds
update_interval=60
# T1 and T2 in fahrenheit - convert if necessary using c2f function
# Example: "T1=$(c2f 30)" will convert 30°C to Fahrenheit
T1=86
T2=110
# Idle-RPM. If you want the Fan to switch of, set this to zero
IDLERPM=0
# Linearly interpolate the fan-speed between RPM1 and RPM2
RPM1=2700
RPM2=3500

# Now loop, check status every $update_interval seconds
while [ 1 ]
do
 # Find out current temperature
 T=`temperature g 0`
 T=${T##*=}
 C=`temperature g 0 | grep -i -c centigrade `
 # Convert to Fahrenheit if output is in Celcius
 if [ $C -gt 0 ]
 then
 T=$(c2f $T)
 fi
 # Check if Temperature is above $T1
 if [ $T -gt $T1 ]; then
 # Keep the fan running
 newRPM=$(( ($RPM1 + ($RPM2 - $RPM1) * ($T - $T1) / ($T2 - $T1)) ))
 else
 # Temp below T1 -> set fan to IDLE-Speed
 newRPM=$IDLERPM
 fi
 fanspeed w $newRPM
 # wait for next cycle
 sleep $update_interval
done

Das Script wid nicht im Ordner start abgelegt, sondern muss extra gestartet werden. Wenn das Skript einfach nur im Ordner start liegt, klappt die Steuerung nicht!

Die Installation kann stark vereinfachen, indem man das Skript direkt auf das NAS herunterlädt. Zunächst muss man sich einloggen, anschließend muss man je nach Festplattenanzahl den gewünschten Befehl eingeben:

  • Code für eine Festplatte ohne Logging: wget http://wolf-u.li/u/167 -O /ffp/lueftersteuerung.sh
  • Code für zwei Festplatten mit Logging: wget http://wolf-u.li/u/169 -O /ffp/lueftersteuerung.sh
  • Code für zwei Festplatten ohne Logging: wget http://wolf-u.li/u/168 -O /ffp/lueftersteuerung.sh
  • Code für Temperaturabhängige Steuerung ohne Logging: wget http://wolf-u.li/u/170 -O /ffp/lueftersteuerung.sh

Anschließend muss immer noch folgendes ausgeführt werden, sofern noch keine Lüftersteuerung installiert war. Kommt beispielsweise nur eine Festplatte hinzu oder wurden die untenstehenden Befehle bereits in das fun_plug eingefügt, sollten diese Befehle nicht mehr ausgeführt werden!

1
2
echo "cp /ffp/lueftersteuerung.sh /sbin" >> /mnt/HD_a2/fun_plug
echo "/sbin/lueftersteuerung.sh >/dev/null 2>/dev/null /dev/null 2>/dev/null" >> /mnt/HD_a2/fun_plug

Wahlweise kann man übrigens auch den “old-school”-Weg gehen und es manuell ablegen:

Im folgenden Beispiel wird das Skript als lueftersteuerung.sh abgespeichert und über das fun_plug gestartet, daher wird folgendes am Ende des fun_plugs eingefügt:

1
2
cp /pfad/zur/lueftersteuerung.sh /sbin
/sbin/lueftersteuerung.sh >/dev/null 2>/dev/null /dev/null 2>/dev/null

Bitte /pfad/zur/ auf den korrekten Pfad anpassen.