That's awesome. I'd love to know more about the script and if you plan to share it. I'm running Ubuntu with very similar setup but my rig is mounted in a wire shelf unit that cost $8 here. Maybe next phase would be something like this.
thank you. I'm happy to share it. the only change I've made to it here is that I removed a few lines that have to do with updating the rrd (round robin database) with some of the stats, since that action is very specific to my setup. the rest should work pretty well for general purposes. let me know if it doesn't, or if you have any questions about it.
python 2.7 (instead of 2.6) was required for something, one of the modules I think, but I don't remember exactly what it was. python 2.6 works fine, I edited the #! line below to reflect this.
#!/usr/bin/python
from re import findall, search
from shlex import split
from subprocess import Popen, PIPE
from sys import stdout, argv
from os import environ
# define target range for temps
TEMP_COOL = 60
TEMP_LOW = 68
TEMP_HIGH = 72
TEMP_CRIT = 80
# define fan speeds limits
FAN_MIN = 20
FAN_MAX = 100
# strings for all hardware polling commands
GET_ADAPTERS = 'aticonfig --list-adapters'
GET_TEMPS = 'aticonfig --odgt --adapter=all'
GET_CLOCKS = 'aticonfig --odgc --adapter=all'
GET_FANS = 'aticonfig --pplib-cmd "get fanspeed 0"'
SET_FANS = 'aticonfig --pplib-cmd "set fanspeed 0 $"'
# make it easier to display terminal text in color
TEXT_COLORS = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"]
def textcolor(text, color):
code = str(TEXT_COLORS.index(color) + 30)
return "\033[0;" + code + "m" + text + "\033[m"
# get all current stats from the hardware (except fans)
raw_adapters = Popen(split(GET_ADAPTERS), stdout=PIPE).communicate()[0]
raw_temps = Popen(split(GET_TEMPS), stdout=PIPE).communicate()[0]
raw_clocks = Popen(split(GET_CLOCKS), stdout=PIPE).communicate()[0]
# make a list of the adapter ids
adapter_ids = findall(r"\*?\s+(\d)\.", raw_adapters)
# getting fan data is a bit specialized and requires some iteration
raw_fans = {}
for i in adapter_ids:
n = int(i)
# the DISPLAY env var needs to be set before each fan is polled
environ["DISPLAY"] = ":0." + i
raw_fans[n] = Popen(split(GET_FANS), stdout=PIPE).communicate()[0]
# all of the parsed stats will be stored here
adapters = []
# iterate over each adapter to parse stats and store them
for i in adapter_ids:
n = int(i)
# parse the stats with regex keeping things as adaptable as possible
temp = search("(?s)" + "Adapter " + i + ".*?" + r"(\d+\.\d+)", raw_temps)
clocks = search("(?s)" + "Adapter " + i + ".*?" + r"(\d+)\s+(\d+)" + ".*?" + r"(\d+)\s+(\d+)" + ".*?" + r"(\d+)%", raw_clocks)
fan = search(r"(\d+)%", raw_fans[n])
# store the parsed data into the adapter list and convert types
adapters.insert(n, {})
cur = adapters[n]
cur["dev"] = n
cur["temp"] = float(temp.group(1))
cur["core"] = int(clocks.group(1))
cur["mem"] = int(clocks.group(2))
cur["pcore"] = int(clocks.group(3))
cur["pmem"] = int(clocks.group(4))
cur["load"] = int(clocks.group(5))
cur["fan"] = int(fan.group(1))
cur["dfan"] = 0
# if temp is outside range then adjust the fan speed up or down
def adjust_fan(cur):
if cur["temp"] < TEMP_LOW: cur["dfan"] = -1
elif cur["temp"] > TEMP_HIGH: cur["dfan"] = 1
while cur["fan"] + cur["dfan"] < FAN_MIN: cur["dfan"] += 1
while cur["fan"] + cur["dfan"] > FAN_MAX: cur["dfan"] -= 1
if cur["dfan"] != 0:
cur["fan"] += cur["dfan"]
environ["DISPLAY"] = ":0." + str(cur["dev"])
command = SET_FANS.replace("$", str(cur["fan"]))
Popen(split(command), stdout=PIPE)
# color the temp display based on its current value
def color_temps(cur):
color = "green"
if cur["temp"] < TEMP_COOL: color = "blue"
elif cur["temp"] < TEMP_LOW: color = "cyan"
elif cur["temp"] > TEMP_CRIT: color = "red"
elif cur["temp"] > TEMP_HIGH: color = "yellow"
cur["temp"] = textcolor("%.1fC" % cur["temp"], color)
# stores the order, label, and format string of each output
outputs = (
("dev", "GPU%d"),
("temp", "%s"),
("load", "%d%%"),
("core", "%d"),
("pcore", "%d"),
("mem", "%d"),
("pmem", "%d"),
("fan", "%d%%"),
("dfan", "%+d%%"))
# print column headers and a row of data for each adapter
# also, adjust fan speeds for each adapter if necessary
for output in outputs: stdout.write(output[0] + "\t")
stdout.write("\n")
for adapter in adapters:
adjust_fan(adapter)
color_temps(adapter)
for output in outputs:
name = output[0]
format = output[1]
value = adapter[name]
stdout.write(format % value + "\t")
stdout.write("\n")