#!/bin/sh # Dell R730xd Fan Controller # Uses local IPMI. No iDRAC username/password required. FAN_NORMAL="0x14" # 20% FAN_WARM="0x19" # 25% FAN_HOT="0x1E" # 30% CPU_WARM=55 CPU_HOT=65 CPU_AUTO=75 INLET_WARM=30 INLET_HOT=35 EXHAUST_AUTO=50 CHECK_INTERVAL=60 CURRENT="" log() { logger "R730xd Fan Controller: $1" } set_manual() { ipmitool raw 0x30 0x30 0x01 0x00 >/dev/null 2>&1 } set_auto() { ipmitool raw 0x30 0x30 0x01 0x01 >/dev/null 2>&1 } set_fans() { set_manual ipmitool raw 0x30 0x30 0x02 0xff "$1" >/dev/null 2>&1 } get_temps() { SDR="$(ipmitool sdr list 2>/dev/null)" INLET="$(echo "$SDR" | awk -F'|' '/Inlet Temp/ {gsub(/ /,"",$2); sub(/degreesC/,"",$2); print int($2)}')" EXHAUST="$(echo "$SDR" | awk -F'|' '/Exhaust Temp/ {gsub(/ /,"",$2); sub(/degreesC/,"",$2); print int($2)}')" CPU_MAX="$(echo "$SDR" | awk -F'|' ' /^Temp[[:space:]]*\|/ { gsub(/ /,"",$2); sub(/degreesC/,"",$2); if (int($2) > max) max=int($2) } END { print max } ')" } cleanup() { log "Stopping - returning fan control to Dell Auto" set_auto exit 0 } trap cleanup INT TERM log "Starting" until ipmitool mc info >/dev/null 2>&1 do sleep 2 done log "IPMI ready" # Set fans immediately after boot set_fans "$FAN_NORMAL" CURRENT="$FAN_NORMAL" log "Initial fan speed set to $FAN_NORMAL" while true do get_temps if [ -z "$CPU_MAX" ] || [ -z "$INLET" ] || [ -z "$EXHAUST" ]; then log "Sensor read failed - returning to Dell Auto" set_auto exit 1 fi if [ "$CPU_MAX" -ge "$CPU_AUTO" ] || [ "$EXHAUST" -ge "$EXHAUST_AUTO" ]; then NEW="AUTO" elif [ "$CPU_MAX" -ge "$CPU_HOT" ] || [ "$INLET" -ge "$INLET_HOT" ]; then NEW="$FAN_HOT" elif [ "$CPU_MAX" -ge "$CPU_WARM" ] || [ "$INLET" -ge "$INLET_WARM" ]; then NEW="$FAN_WARM" else NEW="$FAN_NORMAL" fi if [ "$NEW" != "$CURRENT" ]; then log "CPU=${CPU_MAX}C Inlet=${INLET}C Exhaust=${EXHAUST}C Fan=${NEW}" if [ "$NEW" = "AUTO" ]; then set_auto else set_fans "$NEW" fi CURRENT="$NEW" fi sleep "$CHECK_INTERVAL" done