[TUTORIAL] Script to dynamicaly control ipmi fans depending on host cpu usage

Humay

Renowned Member
Feb 19, 2017
20
6
68
50
I have vibe coded this bash script for inreasing fans speed (auto) on high host cpu usage and dropping to low fans speed when cpu usage is low
enjoy! just run some hungry VM or change HIGH_THRESHOLD=85 like to 45 (becase hyperthreading for example)
you can also remove extra logging for purpose of less SSD wear, anyway it probably cache it in slc or ssd dram cache

nano /usr/local/bin/cpu-automation.sh

Bash:
#!/usr/bin/env bash

# ==============================================================================
# CONFIGURATION
# ==============================================================================
HIGH_THRESHOLD=85   # Trigger high command if CPU is above this %
LOW_THRESHOLD=15    # Trigger low command if CPU falls below this %

STATE_FILE="/tmp/cpu_high_triggered.state"
LOG_FILE="/var/log/cpu-automation.log"

# ==============================================================================
# ACCURATE CPU PERCENTAGE CALCULATION (1-second sample delta)
# ==============================================================================
read -r _ user nice system idle iowait irq softirq steal _ < /proc/stat
prev_total=$((user + nice + system + idle + iowait + irq + softirq + steal))
prev_idle=$((idle + iowait))

sleep 1

read -r _ user nice system idle iowait irq softirq steal _ < /proc/stat
total=$((user + nice + system + idle + iowait + irq + softirq + steal))
idle=$((idle + iowait))

total_delta=$((total - prev_total))
idle_delta=$((idle - prev_idle))
used_delta=$((total_delta - idle_delta))

# Guard against dividing by zero if metrics fail to update
if [ "$total_delta" -le 0 ]; then
    echo "$(date): Error calculating CPU metrics. Skipping run." >> "$LOG_FILE"
    exit 1
fi

CPU_INT=$(( 100 * used_delta / total_delta ))

# ==============================================================================
# AUTOMATION LOGIC
# ==============================================================================
if [ "$CPU_INT" -gt "$HIGH_THRESHOLD" ]; then
    echo "$(date): High CPU detected at ${CPU_INT}%." >> "$LOG_FILE"
 
    # ----------------------------------------------------------------------
    # COMMAND A: RUNS ON HIGH CPU SPIKE
    # Replace the echo line below with your actual high CPU command.
    # ----------------------------------------------------------------------
    echo "Executing High CPU action..." >> "$LOG_FILE"
    # ---- DELL commands for ipmitool for auto fans  DEPENDS ON PLATFORM this is DELL 13 GEN ------
    #ipmitool -I lanplus -H ipaddress -U user -P password raw 0x30 0x30 0x01 0x01
 
    # Flag that the high command ran so the low command is unlocked
    touch "$STATE_FILE"

elif [ "$CPU_INT" -lt "$LOW_THRESHOLD" ]; then
    # Only run if Command A (High CPU) has run previously
    if [ -f "$STATE_FILE" ]; then
        echo "$(date): Low CPU detected at ${CPU_INT}% and High CPU ran previously." >> "$LOG_FILE"
     
        # ------------------------------------------------------------------
        # COMMAND B: RUNS ONLY IF CPU DROPS LOW AFTER A SPIKE
        # Replace the echo line below with your actual low CPU command.
        # ------------------------------------------------------------------
        echo "Executing Low CPU action..." >> "$LOG_FILE"
        #### -- ipmi fans 25 percent DEPENDS ON PLATFORM this is DELL 13 GEN ---
        #ipmitool -I lanplus -H ipaddress -U user -P password raw 0x30 0x30 0x01 0x00
        #ipmitool -I lanplus -H ipaddress -U user -P password raw 0x30 0x30 0x02 0xff 0x19
     
        # Clear the state file to reset the cycle and prevent loops
        rm -f "$STATE_FILE"
    else
        # System is idle, but no previous spike occurred. Do nothing.
        # you can comment next line and put : (colon) on next line
        echo "$(date): Idle at ${CPU_INT}%, skipping action (Waiting for High CPU trigger)." >> "$LOG_FILE"
    fi
else
    # Optional: Log baseline steady-state activity
    echo "$(date): CPU steady at ${CPU_INT}%." >> "$LOG_FILE"
fi

Bash:
crontab -e

* * * * * /usr/local/bin/cpu-automation.sh >/dev/null 2>&1
 
Last edited:
Have you tried using fancontrol? Most servers have integration with lm-sensors so that the system can control the fans just by echoing in a file in /proc.
 
  • Like
Reactions: UdoB