Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save webdev23/88b98b6151d03335a8d24fd9bc3472bd to your computer and use it in GitHub Desktop.
Save webdev23/88b98b6151d03335a8d24fd9bc3472bd to your computer and use it in GitHub Desktop.
Control multiple GPU Fan speed based on CPU temperature - Linux systemd service - Nvidia
This setup allows to provide extra boost of cool air, dedicated for overclocked CPU.
Using the powerful GPU fans based on both CPU and GPU temperature.
As a permanent systemd service, across reboots.
It should be -run once and forget-, make sure to adjust <USER> and always use FULL PATH.
We cannot control GPU fan speed without sudo rights, and various issue arise with display settings.
THe following works great for me, over reboot, and it should work in any Linux.
There is many tricks against issues controlling nvidia-settings, that one works, but:
DONT DO THAT https://askubuntu.com/questions/1411667/unable-to-control-nvidia-fan-speed <= NO NO NO
Instead here is the proper way to run `nvidia-settings` as a systemd service.
Make sure to replace <USER> in all these scripts:
### Remove sudo locks on nvidia-settings ONLY
sudo visudo
Add
root ALL=(ALL) NOPASSWD: /usr/bin/nvidia-settings
<USER> ALL=(ALL) NOPASSWD: /usr/bin/nvidia-settings
### Create file `gpu_auto_fan` in /home/<USER>/.local/bin/gpu_auto_fan - ADJUST AS NEED
```
#!/bin/bash
export DISPLAY=:1.0 # Set the display number MIGHT REQUIRE ADJUSTMENT
export XAUTHORITY=/home/<USER>/.Xauthority # FULL PATH to X authority file
# Function to get the CPU temperature
get_cpu_temp() {
sensors | awk '/Package/ {gsub(/[+°C]/, "", $4); print $4}'
}
# Function to adjust GPU fan speed based on temperatures
adjust_fan_speed() {
local gpu_temp=$1
local cpu_temp=$2
local pcfan=26
local CPU_HOT_THRESHOLD=54
local CPU_BOIL_THRESHOLD=64
# Determine the fan speed based on GPU and CPU temperatures
if (( $(echo "$cpu_temp >= $CPU_BOIL_THRESHOLD" | bc -l) )); then
pcfan=74 # Hardcore hot, higher fan speed
elif (( $(echo "$cpu_temp >= $CPU_HOT_THRESHOLD" | bc -l) )); then
pcfan=50 # CPU hot, moderate fan speed
elif (( $(echo "$gpu_temp < 41" | bc -l) )); then
pcfan=26
elif (( $(echo "$gpu_temp < 46" | bc -l) )); then
pcfan=36
elif (( $(echo "$gpu_temp < 51" | bc -l) )); then
pcfan=40
elif (( $(echo "$gpu_temp < 56" | bc -l) )); then
pcfan=50
elif (( $(echo "$gpu_temp < 60" | bc -l) )); then
pcfan=66
else
pcfan=80 # Max fan speed for high temperatures
fi
# Update fan speed if it has changed
if [[ "$pcfan" -ne "$last_pcfan" ]]; then
echo "Changing fan speed to $pcfan%"
echo "PCFAN=$pcfan" | nvidia-settings -a "[gpu:0]/GPUFanControlState=1" \
-a "[fan:0]/GPUTargetFanSpeed=$pcfan" \
-a "[fan:1]/GPUTargetFanSpeed=$pcfan"
last_pcfan=$pcfan
fi
}
# Initialize last fan speed
last_pcfan=-1
# Main loop
while true; do
gpu_temp=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits | tail -n1)
cpu_temp=$(get_cpu_temp)
adjust_fan_speed "$gpu_temp" "$cpu_temp"
sleep 2
done
```
Make sure `gpu_auto_fan` is executable:
chmod +x gpu_auto_fan
### Then create a systemd service:
Create `gpu_auto_fan.service` (whatever.service):
sudo nano /etc/systemd/system/gpu_auto_fan.service
```
[Unit]
Description=gpu_auto_fan
After=graphical.target
[Service]
Type=simple
ExecStart=/home/<USER>/.local/bin/gpu_auto_fan
Restart=on-failure
User=<USER>
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/<USER>/.Xauthority
[Install]
WantedBy=graphical.target
```
### Then reload systemd:
sudo systemctl daemon-reload
### Enable `gpu_auto_fan` background service.
sudo systemctl enable gpu_auto_fan.service
### Start service
sudo systemctl start gpu_auto_fan.service
# Test carefully!!!
### See logs in journalctl
sudo journalctl -f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment