11#! /bin/bash
22
3- # Define global functions
4- # This function applies Dell's default dynamic fan control profile
3+ for cmd in ipmitool nvidia-smi sensors bc awk; do
4+ if ! command -v $cmd & > /dev/null; then
5+ echo " Error: $cmd is required but not installed."
6+ exit 1
7+ fi
8+ done
9+
510function apply_automatic_fan_control () {
6- # Use ipmitool to send the raw command to set fan control to Dell default
711 ipmitool -I $IDRAC_CONNECTION_STRING raw 0x30 0x30 0x01 0x01 > /dev/null
812 FAN_CONTROL_CURRENT_STATE=$FAN_CONTROL_STATE_AUTOMATIC
913 echo " Fan control set to automatic."
1014}
1115
12- # This function applies a user-specified static fan control profile
1316function apply_manual_fan_control () {
14- # Use ipmitool to send the raw command to set fan control to user-specified value
1517 ipmitool -I $IDRAC_CONNECTION_STRING raw 0x30 0x30 0x01 0x00 > /dev/null
1618 FAN_CONTROL_CURRENT_STATE=$FAN_CONTROL_STATE_MANUAL
1719 echo " Fan control set to manual."
1820}
1921
2022function apply_fan_speed () {
21- # Convert the decimal value to hex
2223 local HEXADECIMAL_FAN_SPEED=$( printf ' 0x%02x' $1 )
2324
2425 ipmitool -I $IDRAC_CONNECTION_STRING raw 0x30 0x30 0x02 0xff $HEXADECIMAL_FAN_SPEED > /dev/null
@@ -27,26 +28,36 @@ function apply_fan_speed () {
2728 echo " Fan speed set to $1 % ($HEXADECIMAL_FAN_SPEED )."
2829}
2930
30- # Retrieve temperature sensors data using nvidia-smi (Edited for multi-gpu compatibility)
3131function retrieve_temperatures () {
32+ # obtain gpu temp from nvidia-smi, select highest
3233 GPU_TEMP=$( nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader | awk ' BEGIN{max=0} {if($1>max) max=$1} END{print max}' )
33- echo " Current Highest GPU Temp: $GPU_TEMP °C"
34+ # obtain cpu temp from lm-sensors, select highest
35+ CPU_TEMP=$( sensors | grep -E ' Core [0-9]+' | awk ' {print $3}' | cut -d' +' -f2 | cut -d' .' -f1 | awk ' BEGIN{max=0} {if($1>max) max=$1} END{print max}' )
36+ # select highest temp between cpu and gpu
37+ if [ $CPU_TEMP -gt $GPU_TEMP ]; then
38+ HIGHEST_TEMP=$CPU_TEMP
39+ TEMP_SOURCE=" CPU"
40+ else
41+ HIGHEST_TEMP=$GPU_TEMP
42+ TEMP_SOURCE=" GPU"
43+ fi
44+ echo " Current Highest GPU Temp: $GPU_TEMP °C, Highest CPU Temp: $CPU_TEMP °C, Using $TEMP_SOURCE Temp: $HIGHEST_TEMP °C"
3445}
3546
36- # Prepare traps in case of script exit
3747function gracefull_exit () {
3848 apply_automatic_fan_control
3949 echo " Script stopped, automatic fan speed restored for safety."
4050 exit 0
4151}
4252
4353function emergency_shutdown () {
44- echo " Emergency termination triggered! GPU temperature ( ${GPU_TEMP} °C) exceeds the threshold ( ${EMRG_TERM_TEMP } °C). "
54+ echo " $( date ) : Emergency shutdown triggered due to $TEMP_SOURCE temp ${HIGHEST_TEMP } °C" >> /var/log/fan_control.log
4555 echo " Shutting down the system immediately!"
56+ sync
4657 shutdown -h now
4758}
4859
49- # Trap the signals for script exit and run gracefull_exit function
60+ # trap signal
5061trap ' gracefull_exit' SIGQUIT SIGKILL SIGTERM EXIT
5162
5263# --- User Configuration ---
@@ -58,62 +69,57 @@ FAN_CONTROL_STATE_AUTOMATIC="automatic"
5869FAN_CONTROL_CURRENT_STATE=$FAN_CONTROL_STATE_AUTOMATIC
5970FAN_CONTROL_MANUAL_PERCENTAGE=0
6071
61- # Linear Fan Speed Algorithm Variables
72+ # Fan Speed Variables
6273MIN_TEMP=65 # Temperature in Celsius to start increasing fan speed
6374MAX_TEMP=90 # Temperature in Celsius at which fan speed reaches maximum
6475MIN_FAN=20 # Minimum fan speed percentage
65- MAX_FAN=100 # Maximum fan speed percentage
66-
67- # Emegerency Termination
76+ MAX_FAN=100 # Maximum fan speed percentage
77+ INTERVAL=3 # Seconds, the interval between temp checks and adjustment
6878
79+ # Emergency Termination
6980EMRG_TERM_STATE=" enabled" # or "disabled". Enabled by default to prevent hw dmg
70- EMRG_TERM_TEMP=100 # in deg celsius, when reached, system will shut down immediately if termination is enabled
81+ EMRG_TERM_TEMP=100 # in deg celsius, when reached, system will shut down immediately if termination is enabled
7182
7283# --- End of User Configuration ---
84+ # do not touch below this point unless you know what you are doing
7385
74- # Non-linear Fan Speed Algorithm
7586while true ; do
76- sleep 2 &
87+ sleep $INTERVAL &
7788 SLEEP_PROCESS_PID=$!
7889
7990 retrieve_temperatures
8091
81- if [[ " $EMRG_TERM_STATE " == " enabled" && $GPU_TEMP -ge $EMRG_TERM_TEMP ]]; then
92+ if [[ " $EMRG_TERM_STATE " == " enabled" && $HIGHEST_TEMP -ge $EMRG_TERM_TEMP ]]; then
8293 emergency_shutdown
8394 fi
8495
85- if (( $GPU_TEMP >= $MIN_TEMP )) ; then
96+ if (( $HIGHEST_TEMP >= $MIN_TEMP )) ; then
8697 if [[ " $FAN_CONTROL_STATE_AUTOMATIC " == " $FAN_CONTROL_CURRENT_STATE " ]]; then
87- echo " GPU temperature is getting high. Enabling manual fan control."
98+ echo " $TEMP_SOURCE temperature is getting high. Enabling manual fan control."
8899 apply_manual_fan_control
89100 fi
90101
91- # Non-Linear Fan Speed Algorithm
92- if (( $GPU_TEMP <= $MAX_TEMP )) ; then
93- # Calculate fan speed using a quadratic formula
94- TEMP_RATIO=$( echo " scale=4; ($GPU_TEMP - $MIN_TEMP ) / ($MAX_TEMP - $MIN_TEMP )" | bc)
102+ if (( $HIGHEST_TEMP <= $MAX_TEMP )) ; then
103+ TEMP_RATIO=$( echo " scale=4; ($HIGHEST_TEMP - $MIN_TEMP ) / ($MAX_TEMP - $MIN_TEMP )" | bc)
95104 FAN_SPEED=$( echo " $MIN_FAN + ($MAX_FAN - $MIN_FAN ) * ($TEMP_RATIO ^ 2)" | bc | awk ' {printf("%d\n", $1 + 0.5)}' )
96105
97- # Ensure fan speed is within bounds
106+ # ensure fan speed is sane
98107 if (( $FAN_SPEED < $MIN_FAN )) ; then
99108 FAN_SPEED=$MIN_FAN
100109 elif (( $FAN_SPEED > $MAX_FAN )) ; then
101110 FAN_SPEED=$MAX_FAN
102111 fi
103112 else
104- # If temperature exceeds MAX_TEMP, set fan to MAX_FAN
105113 FAN_SPEED=$MAX_FAN
106114 fi
107115
108- # Apply fan speed only if it's different from the current manual percentage
109116 if [[ " $FAN_CONTROL_MANUAL_PERCENTAGE " != " $FAN_SPEED " ]]; then
110- echo " Setting fan speed to ${FAN_SPEED} % based on non-linear algorithm."
117+ echo " Setting fan speed to ${FAN_SPEED} % based on non-linear algorithm for $TEMP_SOURCE temperature ."
111118 apply_fan_speed $FAN_SPEED
112119 fi
113120
114121 elif [[ " $FAN_CONTROL_STATE_MANUAL " == " $FAN_CONTROL_CURRENT_STATE " ]]; then
115- # Reset automatic fan control if temperature is below MIN_TEMP and we are currently in manual mode
116- echo " GPU temperature is calming down. Returning to automatic fan control."
122+ echo " $TEMP_SOURCE temperature is calming down. Returning to automatic fan control."
117123 apply_automatic_fan_control
118124 FAN_CONTROL_MANUAL_PERCENTAGE=0
119125 fi
0 commit comments