Small yet powerful POSIX shell fan controller for Linux systems.
It was designed with dell 13/14 gen servers and/or hardware that supports manual fan control through ipmitool or similar utility, but in theory it can be adapted for any system.
Unlike similar scripts, this one is:
- Fully extensible
- Supports per fan control or fan group control
- Supports any sensors and or custom user definable sensors
- Control through user defined or pre made fan curves that can be extended
- Bare bones and fairly minimalistic - no docker required, minimal extra dependencies, it runs directly on the host in basic
sh
The controller needs awk, sensors/lm-sensors, and ipmitool (for supported devices). grep and sed are optional but you might need them.
You need to be root or have root permissions (sudo) in order to proceed!
Clone this repo into /opt/fanctrl and set proper permissions:
sudo mkdir -p /opt/fanctrl && cd "$_" && sudo git clone --depth 1 "https://github.com/SimplyProgrammer/Simple-Universal-Fan-Controller.git" . || exit 1
sudo chown -R root:root /opt/fanctrl
sudo find /opt/fanctrl -type d -exec chmod 750 {} +
sudo find /opt/fanctrl -type f -exec chmod 640 {} +
sudo find /opt/fanctrl -type f -name "_*.sh" -exec chmod 750 {} +
sudo chmod 750 /opt/fanctrl/run-fanctrl
sudo chmod 660 /opt/fanctrl/fanctrl
sudo find /opt/fanctrl/commands -type f -exec chmod 750 {} +
sudo find /opt/fanctrl/sensors -type f -exec chmod 750 {} +Create and enable the service (systemd):
tmp=$(mktemp)
cat > "$tmp" <<EOF
[Unit]
Description=Simple Universal Fan Controller
After=ipmi.service
[Service]
Type=simple
WorkingDirectory=/opt/fanctrl
ExecStart=/opt/fanctrl/run-fanctrl 3
Restart=always
RestartSec=9
[Install]
WantedBy=multi-user.target
EOF
sudo install -o root -g root -m 644 "$tmp" /etc/systemd/system/fanctrl.service
[ -f "$tmp" ] && rm -f "$tmp"
sudo systemctl daemon-reload
sudo systemctl enable --now fanctrl.serviceCheck the service with systemctl status fanctrl.service and view its output
with journalctl -u fanctrl.service.
- run-fanctrl Main script that periodically executes the main pass
- commands/ Hardware-specific manual-control and PWM commands
- _use.sh Activate command files from a hardware profile
- dell-srvr/ Dell server command support implementations
- fans/ One configuration file per physical fan
- _config-fan.sh Interactive fan configuration generator
- configs/ Reusable fan curves: default, silent, turbo, etc.
- commands/ Hardware-specific manual-control and PWM commands
- includes/ Shared shell variables loaded in each pass
- sensors/ Custom pre made sensor
The active hardware commands are commands/enable-manual-fan-ctrl and
commands/set-fan-speed. The active fan files are the regular files or
symlinks directly inside fans/; _-prefixed helper files and subdirectories
are not treated as fans.
Run these commands from the repository root unless noted otherwise.
commands/_use.sh takes a profile directory and symlinks its command files
into commands/. For the included Dell server commands:
cd /opt/fanctrl/commands
./_use.sh dell-srvrLikewise a custom hardware profile should provide
both enable-manual-fan-ctrl and set-fan-speed with the same argument
contracts as the files in commands/.
For servers make sure that you have ipmi support enabled (if required) and ipmitool installed (or other utility that can control the fan speeds).
Note: Supermicro servers are supported as well in theory, but script was only ever tested with dell 13gen server.
Create or update a fan interactively from the fans/ directory. Example:
./_config-fan.sh 0 default ./sensors/cpu-all-coresThe arguments provide defaults for fan name, base config, and sensor command;
the script prompts for confirmation and lets you change them. It creates a
file such as fans/0 containing SENSOR_CMD and, when appropriate, a sourced
FAN_CURVE. Fan names must match the IDs accepted by the hardware command.
Use a profile as a base when several fans share a curve. The generated fan
file can source a file in fans/configs/ or another fan file, then override
SENSOR_CMD for that fan.
The premade custom sensor helpers print a numeric temperature in degrees Celsius:
./sensors/cpu-all-cores # avg, min or max of specified cpu package cores
./sensors/cpu-package 0 # temperature of specified cpu package
./sensors/sensors # avg, min or max of all or specified sensorWhich are expected to be used in particular fans SENSOR_CMD, for instance:
SENSOR_CMD='evl "$(./sensors/cpu-all-cores) + 5"'The bundled curves are:
default: moderate baseline cooling.silent: lower speeds for quieter operation.turbo: max speed sooner.linear: 0% to 100% linear behavior (temp = speed).elbow: quieter <50, louder above it.
Feel free to create your own sensors as well as fan curves.
Its general good practice for the custom ones to be dot files, so they are distinguished.
All of this makes the script equivalent or even superior to what your motherboard UEFI allows.
- Test the selected hardware commands manually before enabling the service.
- Note that script and sensors are not officially designed for sub-zero scenarios.
- Keep a conservative minimum speed -
fanctrluses thresholdsDEFAULT_MIN_SPEED/DEFAULT_MAX_SPEEDas the clamp values when those variables are provided byincludes/. They have default fallbacks and is recommended to not change them. - Ensure every active fan has both
SENSOR_CMDandFAN_CURVE(in place or sourced from base). - In case of any pass errors or termination, the script is configured to immediately hand over control back to the hardware (to disable manual control), preventing thermal issues in case of script failure.
- But note that if your system kernel panics or crashes in such a way that this never occurs it is theoretically possible for the fans to get stuck at low speeds which may result in equipment damage.
Note that author is not responsibly for any such cases!
- But note that if your system kernel panics or crashes in such a way that this never occurs it is theoretically possible for the fans to get stuck at low speeds which may result in equipment damage.