Скрипт контроля частот и вентиляторов видеокарт AMD Radeon
Материал из Linux Wiki
Версия от 11:50, 11 июля 2016; Rain (обсуждение | вклад)
Данный скрипт предназначен для управления частотами и вентиляторами в ригах на базе видеокарт AMD Radeon. Помимо управления, скрипт выводит текущее состояние карт. Если доступно API sgminer (или подобного майнера с такой же структурой вывода данных), то используются его данные и управление отдается ему, а скрипт просто выводит статистику.
ToDo: Дописать
#!/bin/bash
# By Rain ;)
###################################
# IDLE ZONE - [hyst]-[tt1]-[hyst] - ZONE 1 - [hyst]-[tt2]-[hyst] - ZONE 2 - [hyst]-[toh] - OVERHEAT ZONE [Cut-off] - CUT-OFF ZONE
# For example, for 65 / 70 / 80 / 85 and hysteresis level = 1; and fan min=15; target=60 and max=100:
# .............. | 64-66 | ............... | 69-71 | .............. | 79-80 | .......................... | 85 .................
# idle | | zone1 | | zone2 | | overheat | cutoff
# fan down to 15 | do noth. | fan up to 60 | do noth. | fan up to 100 | do noth. | fan to 100; clock step down | halt all; fan to 100
#
# For idle zone fan decremental step is 1%
# For zone 1 fan incremental step is 2%
# For zone 2 fan incremental step is 5%
#
# If temperature goes lower than "$toh-(double hysteresis)" - <=77 C - core clock will be restored to config values
#
# TODO: looks like, no need to use hysteresis in between zone2 and overheat zones anymore
###################################
tt1='65' # First target temperature. Fan will be between fmin and tfan
tt2='70' # Second target temperatune. Fan will be up to fmax
toh='80' # Overheat temperature. Reducing frequencies, fan to fmax
tco='85' # Cut-off temperature. Shutting down all mining processes
hyst='1' # Hysteresis
fmin='15' # Minimal fan speed
tfan='60' # Maximum fan speed for first zone
fmax='100' # Maximum fan speed
ohfs='5' # Overheat frequency reducing step
fups='50' # Clock restore step
trst='75' # Clock restore temperature
sleep='5' # internal timer
corelow='300'
memlow='1000' # not used
conf='/home/rain/config/cards.conf' # cgminer/sgminer config file for getting core/mem frequencies
rrdb='/home/rain/.gpustat.rrd'
site='/tmp/site'
###################################
if [ "${1}" != 'single' ]
then
mkdir -p -m 755 "${site}"
if [ -z "${RRD}" ]
then
if [ -x '/usr/bin/rrdtool' ]
then
rrd='nice -n 19 /usr/bin/rrdtool'
fi
else
rrd=': '
fi
[ ! -e "${rrdb}" ] && ${rrd} create "${rrdb}" \
--step 60 \
DS:gpu0temp:GAUGE:120:U:U \
DS:gpu1temp:GAUGE:120:U:U \
DS:gpu2temp:GAUGE:120:U:U \
DS:gpu3temp:GAUGE:120:U:U \
DS:gpu4temp:GAUGE:120:U:U \
DS:gpu5temp:GAUGE:120:U:U \
DS:gpu6temp:GAUGE:120:U:U \
DS:gpu7temp:GAUGE:120:U:U \
DS:gpu8temp:GAUGE:120:U:U \
DS:gpu9temp:GAUGE:120:U:U \
RRA:MIN:0.5:1:80 \
RRA:MIN:0.5:8:210 \
RRA:MIN:0.5:80:600 \
RRA:MIN:0.5:600:1100 \
RRA:AVERAGE:0.5:1:80 \
RRA:AVERAGE:0.5:8:210 \
RRA:AVERAGE:0.5:80:600 \
RRA:AVERAGE:0.5:600:1100 \
RRA:MAX:0.5:1:80 \
RRA:MAX:0.5:8:210 \
RRA:MAX:0.5:80:600 \
RRA:MAX:0.5:600:1100
mkgraph() {
umask 022
if [ "$3" == 'normal' ];then
size='--width 400 --height 200'
elif [ "$3" == 'large' ]; then
size='--width 900 --height 450'
fi
$rrd graph "${2}" --imgformat PNG \
DEF:gpu0tempmi="${1}":gpu0temp:MIN \
DEF:gpu1tempmi="${1}":gpu1temp:MIN \
DEF:gpu2tempmi="${1}":gpu2temp:MIN \
DEF:gpu3tempmi="${1}":gpu3temp:MIN \
DEF:gpu4tempmi="${1}":gpu4temp:MIN \
DEF:gpu5tempmi="${1}":gpu5temp:MIN \
DEF:gpu6tempmi="${1}":gpu6temp:MIN \
DEF:gpu7tempmi="${1}":gpu7temp:MIN \
DEF:gpu8tempmi="${1}":gpu8temp:MIN \
DEF:gpu9tempmi="${1}":gpu9temp:MIN \
\
DEF:gpu0tempav="${1}":gpu0temp:AVERAGE \
DEF:gpu1tempav="${1}":gpu1temp:AVERAGE \
DEF:gpu2tempav="${1}":gpu2temp:AVERAGE \
DEF:gpu3tempav="${1}":gpu3temp:AVERAGE \
DEF:gpu4tempav="${1}":gpu4temp:AVERAGE \
DEF:gpu5tempav="${1}":gpu5temp:AVERAGE \
DEF:gpu6tempav="${1}":gpu6temp:AVERAGE \
DEF:gpu7tempav="${1}":gpu7temp:AVERAGE \
DEF:gpu8tempav="${1}":gpu8temp:AVERAGE \
DEF:gpu9tempav="${1}":gpu9temp:AVERAGE \
\
DEF:gpu0tempma="${1}":gpu0temp:MAX \
DEF:gpu1tempma="${1}":gpu1temp:MAX \
DEF:gpu2tempma="${1}":gpu2temp:MAX \
DEF:gpu3tempma="${1}":gpu3temp:MAX \
DEF:gpu4tempma="${1}":gpu4temp:MAX \
DEF:gpu5tempma="${1}":gpu5temp:MAX \
DEF:gpu6tempma="${1}":gpu6temp:MAX \
DEF:gpu7tempma="${1}":gpu7temp:MAX \
DEF:gpu8tempma="${1}":gpu8temp:MAX \
DEF:gpu9tempma="${1}":gpu9temp:MAX \
\
CDEF:cdefmida=gpu0tempav,gpu0tempmi,- \
CDEF:cdefmidb=gpu1tempav,gpu1tempmi,- \
CDEF:cdefmidc=gpu2tempav,gpu2tempmi,- \
CDEF:cdefmidd=gpu3tempav,gpu3tempmi,- \
CDEF:cdefmide=gpu4tempav,gpu4tempmi,- \
CDEF:cdefmidf=gpu5tempav,gpu5tempmi,- \
CDEF:cdefmidg=gpu6tempav,gpu6tempmi,- \
CDEF:cdefmidh=gpu7tempav,gpu7tempmi,- \
CDEF:cdefmidi=gpu8tempav,gpu8tempmi,- \
CDEF:cdefmidj=gpu9tempav,gpu9tempmi,- \
\
CDEF:cdefmada=gpu0tempma,gpu0tempav,- \
CDEF:cdefmadb=gpu1tempma,gpu1tempav,- \
CDEF:cdefmadc=gpu2tempma,gpu2tempav,- \
CDEF:cdefmadd=gpu3tempma,gpu3tempav,- \
CDEF:cdefmade=gpu4tempma,gpu4tempav,- \
CDEF:cdefmadf=gpu5tempma,gpu5tempav,- \
CDEF:cdefmadg=gpu6tempma,gpu6tempav,- \
CDEF:cdefmadh=gpu7tempma,gpu7tempav,- \
CDEF:cdefmadi=gpu8tempma,gpu8tempav,- \
CDEF:cdefmadj=gpu9tempma,gpu9tempav,- \
\
LINE2:gpu0tempav#ff0000:'GPU 0' \
LINE0:gpu0tempmi#ff0000: \
AREA:cdefmida#ff000044::STACK \
AREA:cdefmada#ff000044::STACK \
GPRINT:gpu0tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu0tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu0tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu1tempav#ffa800:"GPU 1" \
LINE0:gpu1tempmi#ffa800: \
AREA:cdefmidb#ffa80044::STACK \
AREA:cdefmadb#ffa80044::STACK \
GPRINT:gpu1tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu1tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu1tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu2tempav#fff600:"GPU 2" \
LINE0:gpu2tempmi#fff600: \
AREA:cdefmidc#fff60044::STACK \
AREA:cdefmadc#fff60044::STACK \
GPRINT:gpu2tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu2tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu2tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu3tempav#6cff00:"GPU 3" \
LINE0:gpu3tempmi#6cff00: \
AREA:cdefmidd#6cff0044::STACK \
AREA:cdefmadd#6cff0044::STACK \
GPRINT:gpu3tempmi:MIN:"(Max\: %3.1lf°C \t/" \
GPRINT:gpu3tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu3tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu4tempav#00ffc0:'GPU 4' \
LINE0:gpu4tempmi#00ffc0: \
AREA:cdefmide#00ffc044::STACK \
AREA:cdefmade#00ffc044::STACK \
GPRINT:gpu4tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu4tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu4tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu5tempav#009cff:'GPU 5' \
LINE0:gpu5tempmi#009cff: \
AREA:cdefmidf#009cff44::STACK \
AREA:cdefmadf#009cff44::STACK \
GPRINT:gpu5tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu5tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu5tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu6tempav#0030ff:'GPU 6' \
LINE0:gpu6tempmi#0030ff: \
AREA:cdefmidg#0030ff44::STACK \
AREA:cdefmadg#0030ff44::STACK \
GPRINT:gpu6tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu6tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu6tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu7tempav#c000ff:'GPU 7' \
LINE0:gpu7tempmi#c000ff: \
AREA:cdefmidh#c000ff44::STACK \
AREA:cdefmadh#c000ff44::STACK \
GPRINT:gpu7tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu7tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu7tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu8tempav#d4d2d5:'GPU 8' \
LINE0:gpu8tempmi#d4d2d5: \
AREA:cdefmidi#d4d2d544::STACK \
AREA:cdefmadi#d4d2d544::STACK \
GPRINT:gpu8tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu8tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu8tempma:MAX:"Max\: %3.1lf°C)\n" \
\
LINE2:gpu9tempav#000000:'GPU 9' \
LINE0:gpu9tempmi#000000: \
AREA:cdefmidj#00000044::STACK \
AREA:cdefmadj#00000044::STACK \
GPRINT:gpu9tempmi:MIN:"(Min\: %3.1lf°C \t/" \
GPRINT:gpu9tempav:LAST:"Curr\: %3.1lf°C \t/" \
GPRINT:gpu9tempma:MAX:"Max\: %3.1lf°C)\n" \
${size} \
--title "${4}" \
-s ${5} \
--watermark="${HOSTNAME}" \
--slope-mode \
--lazy 1>/dev/null &
}
# http://localhost/index.html generator
(echo -n "<html><head><style> body {font-family: Courier, monospace;}</style></head><body><b>"
hostname
echo "</b><br><br>"
/home/rain/bin/sysinfo.sh | sed 's/$/<br>/g' | sed 's/ /\ \;/g'
echo "<br><li><a href=/gputemp.html>GPU Temp</a>"
echo "<br><iframe src=/dyn.html frameborder=0 height=50% width=100%></iframe></body></html>") > /tmp/index.html
touch '/tmp/dyn.html'
chmod 644 '/tmp/index.html' '/tmp/dyn.html'
fi
# Never use sgminer API if NOAPI is set
[ ! -z "${NOAPI}" ] && cmd="false :"
showdate() {
echo -ne "\e[0;36m[\e[0;35m"$(date +%Y-%m-%d" "%H:%M:%S)"\e[0;36m]\e[0;0m "
}
# Allow log for debugging purposes
debugme() {
[ "${DEBUG}" == '1' ] && {
showdate
echo "${1}"
} >> /tmp/ffc.log
}
# Halt all GPU activity. Change it if needed
do_halt() {
/home/rain/bin/gpuoff 1>/dev/null 2>/dev/null
/home/rain/bin/ethminerctl suspend
pkill -9 Hashcat
}
# XMPP notifications
#if [ "${1}" != 'single' ]
# then
# rm -f /tmp/sendxmpp 2>/dev/null
# touch /tmp/sendxmpp
# ( tail -qF /tmp/sendxmpp 2>/dev/null | sendxmpp -c -r $(hostname) -i -t rigs@conference.linuxoid.in ) &
#fi
sayto() {
(cat - | tr -d '\n' ; echo -n " on $(hostname)") | sendxmpp -t -r $(hostname) -c rigs@conference.linuxoid.in
# cat - >> /tmp/sendxmpp
}
# cgminer/sgminer core/mem clocks config parser
getcoreconf(){
awk '/gpu-engine/{
gsub(/[0-9]+\-|\"/, "", $3)
split($3, core, ",")
c='$1'+1
print core[c]
}' "${conf}"
}
getmemconf(){
awk '/gpu-memclock/{
gsub(/[0-9]+\-|\"/, "", $3)
split($3, mem, ",")
c='$1'+1
print mem[c]
}' "${conf}"
}
# Function for setting GPU clocks. 1-st parameter is a card number. If parameter is not set - all cards are used
setfreqs() {
[ -z "${1}" ] && card="$(seq 0 $(($(aticonfig --lsa | grep -c '[0-9]\.')-1)))" || card="${1}"
for i in ${card}
do
# Allowing overclocking
aticonfig --od-enable 1>/dev/null
# Getting core and memory clocks. If getcoreconf/getmemconf returns nothing - using GPU 0 clocks
# (sgminer behavior - if one parameter is set - it used for all cards)
core="$(getcoreconf "${i}")"
[ -z "${core}" ] && core="$(getcoreconf 0)"
mem="$(getmemconf "${i}")"
[ -z "${mem}" ] && core="$(getmemconf 0)"
# Setting GPU clocks
[[ ! -z "${core}" && ! -z "${mem}" ]] && {
aticonfig --od-setclocks=$core,$mem --adapter=$i 1>/dev/null
debugme "Setting freqs for GPU $i"
# Clocks state flag. 1 = clocks set from config file, 2 = clocks is reduced.
freqs[$i]='1'
}
done
# Setting Powertune to 120% via atitweak utility
[ -x /home/rain/bin/atitweak ] && /home/rain/bin/atitweak -p 20 > /dev/null
debugme "Setting powertune"
}
###################################
case "${1}" in
freqs)
setfreqs
;;
*)
# [ "${1}" != 'single' ] && echo "Hello, i'm online" | sayto
# Main loop
while :
do
# If NOAPI is not set - checking API availibility
$cmd nc -w 1 -z localhost 4028 && {
api='1' # API detected flag
ffci='0' # $fan array initialisation flag
debugme "API detected"
# Fetching API data
devdata="$(/home/rain/bin/api-example.py devs | sed -r 's/, |\{|\}/\n/g;s/(\n)u|'\''/\1/g')"
} || {
api='0' # API not detected
# sgminer process detection '
# ffci must be set to 0 and $fan array must be filled with real data every time when sgminer started or stopped
if pidof sgminer 1>/dev/null
then
if [ -z "${sgdetect}" ]
then
debugme "sgminer detected"
ffci='0'
sgdetect='1'
fi
else
if [ ! -z "${sgdetect}" ]
then
debugme "sgminer disabled"
unset sgdetect
ffci='0'
fi
fi
debugme "sgminer=$sgdetect"
[ "${ffci}" != '1' ] && {
# init fan array
for j in $(seq 0 $(($(aticonfig --lsa | grep -c '[0-9]\.')-1)))
do
fan[$j]="$(DISPLAY=:0.$j aticonfig --pplib-cmd "get fanspeed 0" | awk '/Result/{gsub(/%/, "", $4); print $4}')"
debugme "Writing array data for GPU $j"
done
# Setting clocks for all cards
if [ "${1}" != 'single' ]
then
setfreqs
fi
ffci='1'
}
# Fetching data from aticonfig utility
atidata="$(aticonfig --odgt --odgc --adapter=all 2>/dev/null)"
debugme "Getting atidata"
#### fans and core frequency control section ####
# Parsing aticonfig output and extracting card number, temperature, core and memory clocks
# TODO: next time use this for all aticonfig data processing. For now we will see core clock updates only in next cycle
for cdat in $(echo "${atidata}" | tr '\n' ' ' | sed 's/Adapter/\n&/g'| sort | sed -nr '/Adapter/N;s/\n/ /gp' | sed -r 's/^Adapter ([0-9]+) - .*Current Peak : *([0-9]+) +([0-9]+).*Temperature - ([0-9]{1,3}).[0-9]+ C.*/\1:\4:\2:\3/g')
do
# Separating values between different variables
cnt="${cdat%:*:*}"
cn="${cnt%:*}" # Card number
#ct="${cnt#*:}" # Card temperature # TODO: use array in the future and remove this variable
ct[$cn]="${cnt#*:}" # Card temperature array
ccmf="${cdat#*:*:}"
ccf="${ccmf%:*}" # Card core clock
cmf="${ccmf#*:}" # Card memory clock
[ "${freqs[$cn]}" == '1' ] && {
cmax[$cn]=${ccf} # max core freq array
mmax[$cn]=${cmf} # max mem freq array
}
debugme "Processing GPU $cn -> ${ct[$cn]} C"
if [ "${1}" != 'single' ]
then
# If card temperature is over $tco - halting mining, fans to $fmax (usually 100%)
[ "${ct[$cn]}" -ge "${tco}" ] && {
# halt mining
debugme "Cutoff temp on $cn"
fan[$cn]=${fmax}
DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fmax}" 1>/dev/null
# showdate >> /tmp/ffc.log
echo "ALERT! Critical temperature (${ct[$cn]}C) on GPU ${cn}" | sayto
do_halt
}
# If card temperature great than $toh, but still less than $tco (80-85 degr. zone) - set fans to max speed and reduce core clocks
[[ "${ct[$cn]}" -ge "${toh}" && "${ct[$cn]}" -lt "${tco}" ]] && {
ftalk='25'
# reduce freqs
debugme "Overheat on ${cn}: ${freqs[$cn]}"
# [ "${freqs[$cn]}" == '1' ] && {
# showdate >> /tmp/ffc.log
# echo "GPU $cn overheat, reducing clocks" >> /tmp/ffc.log
debugme "Setting max fan speed on ${cn}"
fan[$cn]=${fmax}
DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fmax}" 1>/dev/null
[ "${ccf}" -gt "$((${corelow}+${ohfs}))" ] && {
ccf=$((${ccf}-${ohfs}))
[ "${freqs[$cn]}" == '1' ] && {
echo "GPU $cn overheat (${ct[$cn]} C), starting core clock reducing" | sayto
}
freqs[$cn]='2'
debugme "Reducing freqs on $cn to ${ccf}/${cmf}"
aticonfig --od-setclocks=${ccf},${cmf} --adapter=$cn 1>/dev/null
} || {
echo "No more space in frequency range on card ${cn} for clock reducing" | sayto
debugme "No more space in frequency range on card ${cn} for clock reducing"
}
# }
}
# If card temperature goes below overheat level - report about new frequencies
[[ "${ct[$cn]}" -lt "$((${toh}-${hyst}))" ]] && {
[ ${freqs[$cn]} == '2' ] && {
[ ${ftalk} -gt '0' ] && let ftalk-=1
[ ${ftalk} == '1' ] && {
echo "GPU $cn clocks reduced to ${ccf}/${cmf}" | sayto
ftalk='0'
}
}
}
# If card temperature decreased to safe level - $trst - restore core clocks
[[ "${ct[$cn]}" -le "${trst}" ]] && {
[ "${freqs[$cn]}" == '2' ] && {
[ "$((${cmax[$cn]}-${ccf}))" -gt "${fups}" ] && {
aticonfig --od-setclocks=$((${ccf}+${fups})),$cmf --adapter=$cn 1>/dev/null
} || {
setfreqs "${cn}"
debugme "Clocks restored on GPU $cn"
echo "Clocks restored on GPU $cn" | sayto
}
}
}
# If card temperature in second zone (typically 70-80 degr) - allowing fan speed to be up to $fmax
[[ "${ct[$cn]}" -gt "$((${tt2}+${hyst}))" && "${ct[$cn]}" -lt "$((${toh}-${hyst}))" ]] && {
debugme "2-nd fan zone on $cn"
# allow fans to 100%
[ "${fan[$cn]}" -lt "${fmax}" ] && {
# old="${fan[$cn]}"
let fan[$cn]+=5
[ "${fan[$cn]}" -lt "${tfan}" ] && {
fan[$cn]=${tfan}
debugme "Fast heating on $cn"
}
[ "${fan[$cn]}" -gt "${fmax}" ] && fan[$cn]="${fmax}"
debugme "Setting fan to ${fan[$cn]} on GPU $cn"
# showdate >> /tmp/ffc.log
# echo "GPU ${cn} ${ct[$cn]}: setting fan $old -> ${fan[$cn]}" >> /tmp/ffc.log
DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fan[$cn]}" 1>/dev/null
}
}
# If card temperature in 1-st zone (65-70 degr) - fan speed can be up to $tfan
[[ "${ct[$cn]}" -gt "$((${tt1}+${hyst}))" && "${ct[$cn]}" -lt "$((${tt2}-${hyst}))" ]] && {
# allow fans to $tfan
debugme "1-nd fan zone on $cn"
[ "${freqs[$cn]}" == '2' ] && {
setfreqs "${cn}"
}
[ "${fan[$cn]}" -lt "${tfan}" ] && {
# old="${fan[$cn]}"
let fan[$cn]+=2
[ "${fan[$cn]}" -gt "${tfan}" ] && fan[$cn]="${tfan}"
# showdate >> /tmp/ffc.log
# echo "GPU ${cn} ${ct[$cn]}: setting fan $old -> ${fan[$cn]}" >> /tmp/ffc.log
debugme "Setting fan to ${fan[$cn]} on GPU $cn"
DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fan[$cn]}" 1>/dev/null
}
}
# If card temerature less than first target - fan goes idle
[ "${ct[$cn]}" -lt "$((${tt1}-${hyst}))" ] && {
# decrease fan speed
debugme "Low temp on $cn"
# old="${fan[$cn]}"
let fan[$cn]-=1
[ "${fan[$cn]}" -lt "${fmin}" ] && fan[$cn]="${fmin}"
# showdate >> /tmp/ffc.log
# echo "GPU ${cn} ${ct[$cn]}: setting fan $old -> ${fan[$cn]}" >> /tmp/ffc.log
DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fan[$cn]}" 1>>/dev/null
}
fi
done
# TODO: сделать это все как-то покрасивее; возможно - вынести 60 тут и выше (создание базы) в переменную
[ -z "${st}" ] && st='60'
let st-=$((60/$sleep))
[ "${st}" -le '0' ] && {
st='60'
$rrd update "${rrdb}" N$(
s=10
for t in ${!ct[@]}
do
echo -n ":${ct[$t]}"
let s-=1
done
for i in $(seq 1 $s)
do
echo -n :U
done
)
mkgraph "${rrdb}" "${site}"/gpustat.h.png 'normal' "GPU Temp, час" -60min
mkgraph "${rrdb}" "${site}"/gpustat.h.large.png 'large' "GPU Temp, час" -60min
mkgraph "${rrdb}" "${site}"/gpustat.d.png 'normal' "GPU Temp, день" -24h
mkgraph "${rrdb}" "${site}"/gpustat.d.large.png 'large' "GPU Temp, день" -24h
mkgraph "${rrdb}" "${site}"/gpustat.m.png 'normal' "GPU Temp, месяц" -30d
mkgraph "${rrdb}" "${site}"/gpustat.m.large.png 'large' "GPU Temp, месяц" -30d
mkgraph "${rrdb}" "${site}"/gpustat.y.png 'normal' "GPU Temp, год" -12mon
mkgraph "${rrdb}" "${site}"/gpustat.y.large.png 'large' "GPU Temp, год" -12mon
}
devdata="$((
# Exporting fan speed for 2-nd part of this script
for f in ${!fan[@]}
do
echo "Fan Speed $f ${fan[$f]}"
done
# ...and exporting frequency state
for c in ${!freqs[@]}
do
echo "Freq State $c ${freqs[$c]}"
done
# Transforming aticonfig data for sgminer API compatible format... With some additions
echo "${atidata}"
) | awk '
/^Adapter/{
a=$2
name=$0
gsub(/^Adapter.* - /, "", name)
}
/Temp/{
OFMT="%.f"
temp[a]=$5+0
}
/Speed/{
speed[$3]=$4
}
/Freq State/{
freqs[$3]=$4
}
/Clocks/{
core[a]=$4
mem[a]=$5
}
/load/{
load[a]=$4
gsub(/%/, "", load[a])
print "GPU: "a
print "Devname: "name
print "Temperature: " temp[a]
print "Fan Percent: " speed[a]
print "Freq State: " freqs[a]
print "GPU Clock: " core[a]
print "Memory Clock: " mem[a]
print "GPU Activity: " load[a]
print "Status: uAlive"
print "Enabled: U"
print "Utility"
}
')"
}
# Indication part
data="$(echo -n "${devdata}" | gawk '
function pbar(prog, min, max)
{
p=""
if (min=="") min=10
if (max=="") max=100
inc=((max-min)/10)+0.1
for (i=min; i<=max; i+=inc) {
if (i>prog) p=p" "
else p=p"|"
}
return p
}
/Temperature/{
OFMT="%.f"
temp=$2+0
if (temp>79) ctemp="\\e[5;91m"
else
if (temp>69) ctemp="\\e[0;33m"
else
ctemp="\\e[0;32m"
}
/Fan Percent/{
OFMT="%.f"
fan=$3+0
if (fan>75) cfan="\\e[31m"
else
if (fan>45) cfan="\\e[33m"
else
cfan="\\e[32m"
}
/Freq State/{
if ($3=="1") fstate="\\e[32m"
if ($3=="2") fstate="\\e[91m"
}
/GPU Activity/{
act=$3
if (act<80) cact="\\e[0;31m"
else
if (act<90) cact="\\e[0;33m"
else
cact="\\e[0;32m"
}
/GPU Clock/{
core=$3
}
/Devname/{
name=$0
gsub(/Devname: /, " | ", name)
}
/Status/{
stat=$2
if (stat=="uAlive") stat="\\e[36m"
else stat="\\e[5;31m"
}
/Memory Clock/{
mem=$3
}
/Enabled/{
en=$2
if (en=="uN") en="X"
else
if (en=="U") en="U"
else en="Y"
}
/^GPU:/{
gnum=$2
}
/Utility/{
printf "%-67s %-48s %-22s %-61s %s\n",
stat en " GPU "gnum": \\e[0;0m["ctemp pbar(temp, 30, 85) "\\e[0m] " ctemp temp"C\\e[0m",
"| FAN: ["cfan pbar(fan)"\\e[0m] " cfan fan"% \\e[0m",
"| "fstate core"/"mem"\\e[0m",
"| Load: \\e[0;0m["cact pbar(act, 50, 99) "\\e[0m] " cact act"%\\e[0;0m",
name
}'
)"
[ "${api}" == '1' ] &&\
data="\t\t\t=========== sgminer stat ===========\n${data}" ||\
data="\t\t\t=========== aticonfig stat ===========\n${data}"
[ "${1}" == 'single' ] && {
echo -e "${data}"
break
} || {
clear
echo -e "${data}"
# http://localhost/dyn.html generator
(echo -ne "\n* "
echo $(/home/rain/bin/ethspeed single) @ $(date +%H:%M:%S)
echo -ne "\n"
echo -e "${data}") | LANG=C awk '
BEGIN {
print "<html>"
print "<title>"strftime()"</title>"
print "<meta http-equiv=\"refresh\" content=\"10;\">"
print "<head><style> body '{'font-family: Courier, monospace;'}'</style></head><body>"
}
{
gsub(/ /, "\\ ", $0)
gsub(/\t/, "\\ ", $0)
gsub(/$/, "<br>", $0)
gsub(/\[([0-9];)?31m/, "</font><font color=red>", $0)
gsub(/\[([0-9];)?91m/, "</font><font color=red><span class=redcode>", $0)
gsub(/\[([0-9];)?33m/, "</font><font color=darkorange><span class=yellowcode>", $0)
gsub(/\[([0-9];)?32m/, "</font><font color=green><span class=greencode>", $0)
gsub(/\[36m/, "<font color=blue>", $0)
gsub(/\[(0;)?0m/, "</font></span>", $0)
print $0
}
END {
print "</body></html>"
}' > /tmp/dyn.html
}
debugme "Sleeping..."
sleep "${sleep}"
done
;;
esac