I acquired a secondhand IBM x3650 M4 server. Despite being old, this is still a very powerful machine with dual Xeon processors and 384GB of RAM. But it was extremely noisy! The CPU fans sound similar to a vacuum-cleaner.
For simplicity and readability, I will assume that you are using a Debian Linux-based distribution such as Ubuntu or Mint. But with small changes to the commands, the same has been tested to work on Arch-based distros including CachyOS. This can also work under MS-Windows if you install the needed tools.
After some online research, I learned that the fans can be controlled using IPMItool. IPMItool is an open-source command-line utility used for managing and configuring devices that support the Intelligent Platform Management Interface (IPMI). The utility is available for practically all platforms… so to install it under Debian/Ubuntu/Mint etc you would just type:
sudo apt install ipmitool
To set a chosen fan speed, type the following command (substitute $fanspeed with a value between 0 and 255):
sudo ipmitool raw 0x3a 0x07 0xff $fanspeed 0x01
However, I found that sometimes the IPMI would boost the fan-speed, making the server noisy again. So I created a loop to re-issue the command every few seconds. Furthermore, I saw a need to monitor the CPU temperatures and adapt the fan-speed accordingly. On github I discovered this script which looks good (although I have not tried it). Instead, I chose to write my own script using bash (a common Linux command-line shell).
The other scripts that I have seen scale the fan-speed linearly relative to CPU temperature, and that is what the first version of my script did. But then I got the idea to do quadratic scaling. Simplistically, I square the temperature and use that to control the fans. This leads to a behaviour where the fans are very quiet at low temperatures, but ramp-up their speed increasingly rapidly as temperatures increase. This script keeps my server quiet, and seems to maintain temperatures below 50°C.
If you desire extra cooling, then please try modifying the mindegrees constant in the script. If you increase the value, the fans will be quieter but your system will run at a higher temperature. If you decrease the value, the fans will be a bit more noisy but your system will run cooler. I have experimented with values of 25° and 30° (degrees).
The maxdegrees constant defines the temperature at which the fans will run at full-power. I have set this safely to 75°, although the specifications for my Xeon CPUs suggest that they can run at up to 85°. You could try modifying the value of maxdegrees if you wish…. it will change the quadratic cooling curve. Your system should run quieter if you increase this value… at your own risk!!
Here is a sample output from that script when running:
> ./spinningstarauto.sh
-=# Making the fans Quiet (adjust speed by temperature) #=-
Fan minimum=30°, maximum=75° Celcius. Quadratic scaling...
[|] [/] [-] [\] Temp: 42° Fanspeed: 9% (0x19)
Here is the script that I wrote (spinningstarauto.sh) to control the fans. The code is quite rough, but it works well for me:
#!/bin/bash
# NB - this script requires SUDO permission for impmitool
# Quick workaround - set SUID bit on ipmitool to avoid needing to run this script with sudo, otherwise you will need to type a password. NB - there are security risks to setting the impitool SUID bit. Do so at your own discretion.
# at mindegrees or below, there will be no (zero) fans
mindegrees=30
# at maxdegrees fans will be 100% - we don't want to let the machine exceed this
maxdegrees=75
# For printing visual spinning fans
charsa="-\|/-\|/"
# speedfactor affects how fast the visual fans will spin
# a value of 0x80 seems good, but increase to make vis.fans spin slower...
speedfactor=0x80
printf " -=# Making the fans Quiet (adjust speed by temperature) #=-\n"
printf " Fan minimum=$mindegrees°, maximum=$maxdegrees° Celcius. Quadratic scaling...\n"
# initialise these variables so they don't have to be in the loop
myrange=$(($maxdegrees-$mindegrees))
fanlength=${#charsa}
while true; do
temp=$(cat /sys/class/thermal/thermal_zone0/temp)
degrees=$(($temp/1000))
temprelative=$(($degrees-$mindegrees))
# catch temps less than mintemp, could cause a negative result
if [ $temprelative -lt 0 ]; then temprelative=0; fi
# xval will be in the range 0..10 (temperature)
xval=$(echo "10*$temprelative/$myrange" | bc -l)
# square xval so that it will be in range 0..100 - and provides exponential scaling
procent=$(echo "scale=0; ($xval*$xval)/1" | bc -l)
# calculate fan speed as a percentage of 0xFF (255 is max)
fanspeed=$(echo "scale=0; ($procent*255/100)" | bc -l)
# sanity check: make sure fanspeed is < 256...
# otherwise something weird/dangerous might happen!
if [ $fanspeed -gt 255 ]; then fanspeed=255; fi
# suppress output of ipmitool command
ipmitool raw 0x3a 0x07 0xff $fanspeed 0x01 >> /dev/null
printf " [/] [#IPMI] [|] Temp: $degrees° Fanspeed: $procent%% (0x%x) \r" $fanspeed
for (( i=0; i<$fanlength; i++ )); do
sleep 0.2 #$(($speedfactor / ($fanspeed)))
fanstring=""
for ((fan=0; fan<4; fan++)); do
fanstring="${fanstring} [${charsa:(($i+$fan)%fanlength):1}]"
done
printf "${fanstring}\r"
done
done
This script made The World of Difference for me! Now I can use my x3650 even when my lady is sleeping.
Disclaimer – of course, if your computer overheats, there is a risk of damaging it. By controlling the fans this way it is possible that your computer might not receive adequate cooling. Watch your temperatures closely. I will not be held responsible for any damages. Use my script at your own risk.
I developed and tested this script during cold winter weather. It is possible that in the hot summer, we might discover that the script needs to be modified. Despite all that, it has been working well for me and I do not anticipate any future problems.
If you are not using Ubuntu, it should be easy-enough to adapt this script to a different OS. Furthermore, this script could be adapted to work on machines other than the IBM x3650 M4. Feel free to drop a comment if you would like me to explain further.


Leave a Reply