Difference between revisions of "Fan control scripts"
(Ref patch for controlling fan speed) |
(New script with speed control) |
||
Line 1: | Line 1: | ||
==Fan control shell scripts== | ==Fan control shell scripts== | ||
− | + | ===<tt>sh</tt> script example=== | |
− | |||
− | ===sh script example=== | ||
#!/bin/sh | #!/bin/sh | ||
Line 25: | Line 23: | ||
done | done | ||
− | ===sh script with more features=== | + | ===<tt>sh</tt> script with more features=== |
#!/bin/sh | #!/bin/sh | ||
Line 80: | Line 78: | ||
done | done | ||
− | ===sh script with extra safety functionality === | + | ===<tt>sh</tt> script with extra safety functionality === |
ibm_acpi usually works well. But to rely on it completely, this script provides some extra safety functionality: | ibm_acpi usually works well. But to rely on it completely, this script provides some extra safety functionality: | ||
# It catches various signals and turns the fan on before it quits. | # It catches various signals and turns the fan on before it quits. | ||
Line 125: | Line 123: | ||
sleep 5 | sleep 5 | ||
done | done | ||
+ | |||
+ | ===<tt>sh</tt> script with fine control over fan speed=== | ||
+ | While the above scripts only toggle the fan on and off, the following also sets the fan speed according to sytem temperatures. It requires the [[patch for controlling fan speed]]. | ||
+ | |||
+ | <pre> | ||
+ | #!/bin/sh | ||
+ | # This script is public domain. | ||
+ | |||
+ | LEVELS=( 0 2 4 7) # fan speed levels | ||
+ | UP_TEMPS=( 54 62 68 ) # speed increase trip points | ||
+ | DOWN_TEMPS=( 50 58 64 ) # speed decrease trip points | ||
+ | |||
+ | IBM_ACPI=/proc/acpi/ibm | ||
+ | FAN=$IBM_ACPI/fan | ||
+ | INTERVAL=3 | ||
+ | VERBOSE=true | ||
+ | DRY_RUN=false | ||
+ | |||
+ | [[ "$1" == "-t" ]] && { DRY_RUN=true; echo "$0: Dry run, will not change fan state."; } | ||
+ | |||
+ | # Enable the fan in default mode if anything goes wrong: | ||
+ | set -e | ||
+ | $DRY_RUN || trap "echo enable > $FAN; exit 0" EXIT HUP KILL INT ABRT STOP QUIT SEGV TERM | ||
+ | |||
+ | |||
+ | thermometer() { # output list of temperatures | ||
+ | cat $IBM_ACPI/thermal | { | ||
+ | read X Y | ||
+ | [[ "$X" == "temperatures:" ]] || { | ||
+ | echo "$0: Bad temperatures: $X $Y" >&2 | ||
+ | exit 1 | ||
+ | } | ||
+ | echo "$Y"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | speedometer() { # output fan speed | ||
+ | cat $FAN | sed '/^speed/!d; s/speed:[ \t]*//' | ||
+ | } | ||
+ | |||
+ | IDX=0 | ||
+ | MAX_IDX=$(( ${#LEVELS[@]} - 1 )) | ||
+ | |||
+ | while true; do | ||
+ | NEWIDX=$IDX | ||
+ | DOWN=$(( IDX > 0 )) | ||
+ | TEMPS=`thermometer` | ||
+ | $VERBOSE && SPEED=`speedometer` | ||
+ | |||
+ | for TEMP in $TEMPS; do | ||
+ | # Increase? | ||
+ | while [[ $NEWIDX -lt $MAX_IDX ]] && | ||
+ | [[ $TEMP -ge ${UP_TEMPS[$NEWIDX]} ]]; do | ||
+ | (( NEWIDX ++ )) | ||
+ | DOWN=0 | ||
+ | done | ||
+ | # Decrease? | ||
+ | if [[ $DOWN == 1 ]] && | ||
+ | [[ $TEMP -gt ${DOWN_TEMPS[$(( IDX - 1 ))]} ]]; then | ||
+ | DOWN=0 | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | if [[ $DOWN == 1 ]]; then | ||
+ | NEWIDX=$(( IDX - 1 )) | ||
+ | fi | ||
+ | |||
+ | OLDLEVEL=${LEVELS[$IDX]} | ||
+ | NEWLEVEL=${LEVELS[$NEWIDX]} | ||
+ | $VERBOSE && echo "$0: Temps: $TEMPS Fan: $SPEED Level: $OLDLEVEL->$NEWLEVEL" | ||
+ | $DRY_RUN || echo level $NEWLEVEL > $FAN | ||
+ | IDX=$NEWIDX | ||
+ | sleep $INTERVAL | ||
+ | done | ||
+ | </pre> | ||
==Init script example== | ==Init script example== |
Revision as of 20:59, 25 October 2005
Contents
Fan control shell scripts
sh script example
#!/bin/sh MAXTEMP=50 while [ 1 ]; do fan=no for temp in `sed s/temperatures:// < /proc/acpi/ibm/thermal` do test $temp -gt $MAXTEMP && fan=yes done command='disable' test "$fan" = "yes" && command='enable' echo $command > /proc/acpi/ibm/fan sleep 20 done
sh script with more features
#!/bin/sh # fan control-script # # based upon ibm-acpi 0.11 (experimental=1 !) # # eliminates anoying "fan always on" in battery mode # works with hysteresis (DELTA) so that always-turn-on/turn-off is avoided # fan acivates at MAXTEMP and cools down CPU, GPU etc. to MAXTEMP-DELTA than the fan is turned off # furthermore detects if AC is on and gives back fan control to default behaviour than # # one can change MAXTEMP and DELTA to individual values # but take care of your THINKPAD don`t melt it! # # have fun! # mk 05.05.05 MAXTEMP=51 DELTA=4 SWITCHTEMP=$MAXTEMP #make sure the script doesn't leave the fan off on error trap "echo enable > /proc/acpi/ibm/fan" EXIT while [ 1 ]; do for ac in `sed s/state:// < /proc/acpi/ac_adapter/AC/state` do if [ "$ac" = "off-line" ]; then fan=no for temp in `sed s/temperatures:// < /proc/acpi/ibm/thermal` do test $temp -gt $SWITCHTEMP && fan=yes done if [ "$fan" = "yes" ]; then command='enable' SWITCHTEMP=`expr $MAXTEMP - $DELTA` else SWITCHTEMP=$MAXTEMP command='disable' fi else # ac-adapter on -> set fan control to standard behaviour command='enable' fi echo $command > /proc/acpi/ibm/fan sleep 15 done done
sh script with extra safety functionality
ibm_acpi usually works well. But to rely on it completely, this script provides some extra safety functionality:
- It catches various signals and turns the fan on before it quits.
- It turns off the fan under very strict conditions, leaving it on when unexpected errors occur.
#!/bin/sh # july 2005 Erik Groeneveld, erik@cq2.nl # It makes sure the fan is on in case of errors # and only turns it off when all temps are ok. IBM_ACPI=/proc/acpi/ibm THERMOMETER=$IBM_ACPI/thermal FAN=$IBM_ACPI/fan MAXTRIPPOINT=65 MINTRIPPOINT=60 TRIPPOINT=$MINTRIPPOINT echo fancontrol: Thermometer: $THERMOMETER, Fan: $FAN echo fancontrol: Current `cat $THERMOMETER` echo fancontrol: Controlling temperatures between $MINTRIPPOINT and $MAXTRIPPOINT degrees. # Make sure the fan is turned on when the script crashes or is killed trap "echo enable > $FAN; exit 0" HUP KILL INT ABRT STOP QUIT SEGV TERM while [ 1 ]; do command=enable temperatures=`sed s/temperatures:// < $THERMOMETER` result= for temp in $temperatures do test $temp -le $TRIPPOINT && result=$result.Ok done if [ "$result" = ".Ok.Ok.Ok.Ok.Ok.Ok.Ok.Ok" ]; then command=disable TRIPPOINT=$MAXTRIPPOINT else command=enable TRIPPOINT=$MINTRIPPOINT fi echo $command > $FAN # Temperature ramps up quickly, so pick this not too large: sleep 5 done
sh script with fine control over fan speed
While the above scripts only toggle the fan on and off, the following also sets the fan speed according to sytem temperatures. It requires the patch for controlling fan speed.
#!/bin/sh # This script is public domain. LEVELS=( 0 2 4 7) # fan speed levels UP_TEMPS=( 54 62 68 ) # speed increase trip points DOWN_TEMPS=( 50 58 64 ) # speed decrease trip points IBM_ACPI=/proc/acpi/ibm FAN=$IBM_ACPI/fan INTERVAL=3 VERBOSE=true DRY_RUN=false [[ "$1" == "-t" ]] && { DRY_RUN=true; echo "$0: Dry run, will not change fan state."; } # Enable the fan in default mode if anything goes wrong: set -e $DRY_RUN || trap "echo enable > $FAN; exit 0" EXIT HUP KILL INT ABRT STOP QUIT SEGV TERM thermometer() { # output list of temperatures cat $IBM_ACPI/thermal | { read X Y [[ "$X" == "temperatures:" ]] || { echo "$0: Bad temperatures: $X $Y" >&2 exit 1 } echo "$Y"; } } speedometer() { # output fan speed cat $FAN | sed '/^speed/!d; s/speed:[ \t]*//' } IDX=0 MAX_IDX=$(( ${#LEVELS[@]} - 1 )) while true; do NEWIDX=$IDX DOWN=$(( IDX > 0 )) TEMPS=`thermometer` $VERBOSE && SPEED=`speedometer` for TEMP in $TEMPS; do # Increase? while [[ $NEWIDX -lt $MAX_IDX ]] && [[ $TEMP -ge ${UP_TEMPS[$NEWIDX]} ]]; do (( NEWIDX ++ )) DOWN=0 done # Decrease? if [[ $DOWN == 1 ]] && [[ $TEMP -gt ${DOWN_TEMPS[$(( IDX - 1 ))]} ]]; then DOWN=0 fi done if [[ $DOWN == 1 ]]; then NEWIDX=$(( IDX - 1 )) fi OLDLEVEL=${LEVELS[$IDX]} NEWLEVEL=${LEVELS[$NEWIDX]} $VERBOSE && echo "$0: Temps: $TEMPS Fan: $SPEED Level: $OLDLEVEL->$NEWLEVEL" $DRY_RUN || echo level $NEWLEVEL > $FAN IDX=$NEWIDX sleep $INTERVAL done
Init script example
#! /bin/sh N=/etc/init.d/fan set -e case "$1" in start) # make sure privileges don't persist across reboots if [ -d /var/run/fan ] && [ "x`ls /var/run/fan`" != x ] then touch -t 198501010000 /var/run/fan/* fi fan.sh & # Script from above ;; stop|reload|restart|force-reload) killall fan.sh echo enable > /proc/acpi/ibm/fan ;; *) echo "Usage: $N {start|stop|restart|force-reload}" >&2 exit 1 ;; esac exit 0
Init script example for gentoo
Assume one of the above control scripts is /usr/sbin/ibm-fancontrold, for gentoo use the following init script in /etc/init.d/ibm-fancontrol. Copy the script to /etc/init.d/ibm-fancontrol, then do
# rc-update add ibm-fancontrol default
This will add the init script to the default runlevel.
#!/sbin/runscript # 2005 Gilbert Tiefengruber # Distributed under the terms of the GNU General Public License v2 # IBM Fancontrol init script for IBM Thinkpad laptops (tested with R50) # This init script was written for gentoo 2005.1, kernel 2.6.12 # You need the ibm_acpi kernel module version 0.11 or greater # load the module with experimental=1 to enable the fan controls depend() { need localmount } checkconfig() { if [ ! -e /proc/acpi/ibm/fan ]; then eerror "The ibm_acpi module must be loaded with (experimental=1)" return 1 fi } start() { checkconfig || return 1 ebegin "Starting ibm-fancontrold" start-stop-daemon --quiet -p /var/run/ibm-fancontrold.pid -m -b --start -a /usr/sbin/ibm-fancontrold eend ${?} } stop() { ebegin "Stopping ibm-fancontrold" start-stop-daemon --stop --quiet -p /var/run/ibm-fancontrold.pid eend ${?} }
fanctrld
fanctrld is a daemon (written in C) that controls the Thinkpad's fan. The basic approach is to monitor both temperature and fan speed. The fan is enabled when a certain temperature is exceeded, and disabled when the BIOS slows down the fan below a certain speed.