#!/bin/bash # This is to control the speed of the system fan on a QNAP TS-410 running # Debian depending on the temperatures the harddisks report via SMART. # AFAIK it should work on every QNAP TS-41x as long as it runs # Debian (tested on 6.0.2, "squeeze"). # # (c) 2011 Robert Waldner # License: GPLv2, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html # # Needs smartmontools installed, obviously, and qcontrol running. # It's ugly, I know. # Hopefully there'll be something built-in to qcontrol at some point. set -e DISKS="a b c d" MAXTEMP=34 MEDTEMP=30 MINTEMP=20 # writing to /var/log would wake the disks when idle LOG=/tmp/fancontrol.log DATE=`date --rfc-822` # don't make the loop too tight, at least my disks block for 1-2 seconds # while answering SMART requests SLEEP=60 LASTSTATE="undef" TEMPFILE=/tmp/disktemps while true; do DATE=`date --rfc-822` LOGLINE=`echo -n "$DATE:"` HIGHEST=0 for DISK in $DISKS ; do # hddtemp would wake the disks, smartctl allegedly doesn't TEMP=`/usr/sbin/smartctl -a "/dev/sd$DISK" \ | grep Temperature_Celsius \ | sed -e s/".*\-"//g -e s/"(.*"//g -e s/"\ "//g` LOGLINE=`echo -n "$LOGLINE sd$DISK: $TEMP;"` TEMPLINE=`echo -n "$TEMPLINE $TEMP"` if [ "$TEMP" -gt "$HIGHEST" ]; then HIGHEST="$TEMP" fi done # write the current temps to a file for easy access from other stuff. # file must not grow, and should not reside on any physical disk # so as not to wake sleeping drives. echo "$TEMPLINE" >"$TEMPFILE.1" mv "$TEMPFILE.1" "$TEMPFILE" # damn qcontrol exits with something <> 0 even on success if [ "$HIGHEST" -ge "$MAXTEMP" ]; then if [ "$LASTSTATE" != "full" ]; then LOGLINE=`echo -n "$LOGLINE Fan: full"` LASTSTATE="full" qcontrol fanspeed full || true echo "$LOGLINE" >>"$LOG" fi elif [ "$HIGHEST" -ge "$MEDTEMP" ]; then if [ "$LASTSTATE" != "medium" ]; then LOGLINE=`echo -n "$LOGLINE Fan: medium"` LASTSTATE="medium" qcontrol fanspeed medium || true echo "$LOGLINE" >>"$LOG" fi elif [ "$HIGHEST" -ge "$MINTEMP" ]; then if [ "$LASTSTATE" != "silence" ]; then LOGLINE=`echo -n "$LOGLINE Fan: silence"` LASTSTATE="silence" qcontrol fanspeed silence || true echo "$LOGLINE" >>"$LOG" fi else echo "$DATE: CONFUSION; last state: $LASTSTATE; highest temp: $HIGHEST; trying to set the fan to full and exiting" >>"$LOG" qcontrol fanspeed full || true exit fi sleep "$SLEEP" done