Skip to content

Instantly share code, notes, and snippets.

@haxwithaxe
Created June 18, 2021 18:14
Show Gist options
  • Save haxwithaxe/93d1b6b66220a6f3d90cdf73450d16bd to your computer and use it in GitHub Desktop.
Save haxwithaxe/93d1b6b66220a6f3d90cdf73450d16bd to your computer and use it in GitHub Desktop.
A script to adjust the fan speed on a Supermicro X9 motherboard based on hard drive temperatures.
#!/usr/bin/env python3
"""A script to adjust the fan speed on a Supermicro X9 motherboard based on
hard drive temperatures.
Install to `/usr/local/sbin/coolhddx9` for use with the associated systemd
service and timer.
"""
import glob
import os
import subprocess
MAX_TEMP = 39 # Magic number from a differnt script found online
FULL = '0x01' # "Maximum cooling"
OPTIMAL = '0x02' # "Balanced fan speed and power consumption"
def get_temp(hdd):
"""Get the temperature of `hdd` from `smartctl`.
Arguments:
hdd (str): The path to a hard drive block device.
Returns:
int: The temperature of `hdd` or 0 if a temperature can't be found.
"""
try:
lines = subprocess.check_output(['smartctl', '--attributes', hdd])
except subprocess.CalledProcessError as err:
print('Error:', err)
return 0
for line in lines.split(b'\n'):
if b'Temp' in line:
# Sometimes there is a "(Min/Max n/n)" at the end of the line.
# This gives "n/n)" in the last index.
try:
# No min/max
return int(line.split()[-1])
except ValueError:
# Min/max. Use a different index.
return int(line.split()[-3])
print('Error: No temp found for', hdd)
return 0
def set_mode(mode):
"""Set the fan mode of the motherboard."""
proc = subprocess.run(['ipmitool', 'raw', '0x30', '0x45', '0x01', mode],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if proc.returncode != 0:
print('Error:', proc.stdout)
def _main():
for hdd in glob.glob('/dev/sd[a-z]'):
if get_temp(hdd) > MAX_TEMP:
set_mode(FULL)
return
set_mode(OPTIMAL)
if __name__ == '__main__':
_main()
[Unit]
Description=HDD tempurature manager
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/coolhddx9
[Unit]
Description=HDD tempurature manager
[Timer]
OnBootSec=10m
OnUnitActivate=10m
Unit=coolhddx9.service
[Install]
WantedBy=timers.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment