[SOLVED] Bash script: Automatic BOINC temperature regulation
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Bash script: Automatic BOINC temperature regulation
Hi all,
I wrote a simple bash script to change the CPU usage according to its temperature.
I wrote this for my AMD Athlon 64 X2 (R) [2006] on Debian Wheezy (should also work on Ubuntu ...?). You'll need the packages lm-sensors and sed. Note that you have to start this as root or with sudo rights (to change the BOINC owned preferences file).
The only thing I haven't got rid of is that it will output twice at start if you hit a time that corresponds with the OUTPUTPAUSE.
Suggestions and changes are welcome. I will update this post.
Use your favorite internet search enginge for your CPU's suggested temperature and set TARGTEMP.
I've set the interval of usage changes to 25 seconds and value of usage change to 4 %. This gives me quite stable output to the terminal. I'm not sure of decreasing the interval or increasing the value because this might influence the crunch results negatively.
Code:
#!/bin/bash
#Script to adapt BOINC's global CPU usage to CPU temperature
#Use your favorite internet search enginge
#for your CPU's suggested temperature
#Written for AMD Athlon 64 X2 (R) [2006]
#
#Released into the Public Domain or CC0, your choice.
#Thanks to grymoire.com, tldp.org, stackoverflow.com
#and all of the Free, Libre, Open Source Community.
#Version 0.2
#
#Usage:
#You can give the CPU usage as an argument and the script
#will set it and exit
#Run it without argument and it will adjust according to temperature
#Set target temperature of your CPU in Degree Celsius here:
TARGTEMP=50
#Value changes of CPU usage in percent
USAGELEAPS=4
#Can be adjusted in line 60 and 61 (e. g. -1 or +5).
#Set interval between usage changes (in seconds)
CHANGEPAUSE=25
#Set interval between screen outputs (in minutes)
OUTPUTPAUSE=5
#Simple check for dependencies
DEPENDENCIES="sensors sed"
for i in $DEPENDENCIES; do
if ! command -v "$i" >/dev/null
then echo "Please check if you have the package necessary for \033[1m$i\033[0m installed." && exit 1; fi; done
#Display (a kind of) progress bar graph of advised CPU usage
output () {
echo -n "$CURRTEMP °C "
echo -n $(date +"%H:%M")
for i in $(seq 1 "$ADVCPU"); do echo -n "="; done
echo -n "$ADVCPU"% && echo
}
#Change to BOINC_DIR and create temporary folder for backup
BOINCDAT=$(grep BOINC_DIR /etc/default/boinc-client | grep -v "^#" | cut -d"\"" -f2)
cd $BOINCDAT
mkdir -p tmp
#Set counter before "while loop" (v)
COUNTER=0
#Begin loop if BOINC is running
while [ -f "lockfile" ]; do
#Grab current CPU usage settings
CURRCPU=$(grep "<cpu_usage_limit>" global_prefs_override.xml | cut -d">" -f2 | cut -d"." -f1)
#Grab current temperature
CURRTEMP=$(sensors | grep "Core1 Temp" | head -1 | cut -d"+" -f2 | cut -d"." -f1)
#In-/Decrease usage by ^USAGELEAPS
if [[ "$CURRTEMP" -gt "$TARGTEMP" && "$CURRCPU" -gt "$USAGELEAPS" ]]
then ADVCPU=$(( $CURRCPU-$USAGELEAPS ))
else ADVCPU=$(( $CURRCPU+$USAGELEAPS ))
fi
#If argument given set it as CPU usage
[ -n "${1}" ] && ADVCPU=$1
#Puts out advised CPU usage once at start (^ COUNTER=0)
if [ "$COUNTER" = 0 ]; then
output
COUNTER=1
fi
#Calculates pause for output on screen and to log by remainder
MINUTE=$(date +"%-M")
REMAINDER=$(( $MINUTE % $OUTPUTPAUSE ))
if [ "$REMAINDER" = 0 ] && [ "$MINUTE" != "$OLDMINUTE" ]; then
output
#Save time to compare as to not output more than once in the same minute
OLDMINUTE="$MINUTE"
fi
#Stream EDit line with cpu_usage_limit by substituting CURRCPU with ADVCPU
sed '/cpu_usage_limit/ s/'$CURRCPU'/'$ADVCPU'/' <global_prefs_override.xml >tmp/global_prefs_override.xml
#Check temporary backup and copy to original (errors go to output AND into boinctemp.log)
if grep "<cpu_usage_limit>"$ADVCPU"" tmp/global_prefs_override.xml 2>&1>/dev/null | tee -a boinctemp.log
then cp tmp/global_prefs_override.xml global_prefs_override.xml
else echo "Can't edit preferences file. Check your disk." && exit 1
fi
boinccmd --read_global_prefs_override
#if usage is given as argument, exit
[ -n "${1}" ] && exit
sleep "$CHANGEPAUSE"s
done
Apologies to other flavour users but this should be easily adaptable.
#!/bin/bash
#Script to adapt BOINC's global CPU usage to CPU temperature
#Use your favorite internet search enginge
#for your CPU's suggested temperature
#Written for AMD Athlon 64 X2 (R) [2006]
#
#Released into the Public Domain or CC0, your choice.
#Thanks to grymoire.com, tldp.org, stackoverflow.com
#and all of the Free, Libre, Open Source Community.
#Version 0.5
#
#Usage:
#You can give the CPU usage as an argument
# and the script will set it and exit
#Run it without argument and it will adjust according to temperature
#Set target temperature of your CPU in Degree Celsius here:
TARGTEMP=60
#Value changes of CPU usage in percent
USAGELEAPS=4
#Can be adjusted in line 60 and 61.
#Set interval between usage changes (in seconds)
CHANGEPAUSE=60
#Set interval between screen outputs (in minutes)
OUTPUTPAUSE=1
#Simple check for dependencies
DEPENDENCIES="sensors sed"
for i in $DEPENDENCIES; do
if ! command -v "$i" >/dev/null
then echo "Please check if you have the package necessary for \033[1m$i\033[0m installed." && exit 1; fi; done
#Function for displaying (a kind of) progress bar graph of advised CPU usage
output () {
echo -n "$CURRTEMP °C "
echo -n $(date +"%H:%M")
echo -n " $ADVCPU"% && echo
}
#Change to BOINC_DIR and create temporary folder for backup
BOINCDAT=$(grep BOINC_DIR /etc/default/boinc-client | grep -v "^#" | cut -d"\"" -f2)
cd $BOINCDAT
mkdir -p tmp
#Set counter before "while loop" (v)
COUNTER=0
#Begin loop if BOINC is running
while [ -f "lockfile" ]; do
#Grab current CPU usage settings
CURRCPU=$(grep "<cpu_usage_limit>" global_prefs_override.xml | cut -d">" -f2 | cut -d"." -f1)
#Grab current temperature
CURRTEMP=$(sensors | grep "Core1 Temp" | head -1 | cut -d"+" -f2 | cut -d"." -f1)
#Make sure that advised CPU usage will not fall under 1
#In-/Decrease usage by ^USAGELEAPS
if [[ "$TARGTEMP" -ge "$CURRTEMP" ]]
then if [[ "$ADVCPU" -lt 100-"$USAGELEAPS" ]]
then ADVCPU=$(( $CURRCPU+$USAGELEAPS ))
else ADVCPU=99
fi
fi
if [[ "$TARGTEMP" -lt "$CURRTEMP" ]]
then if [[ "$ADVCPU" -gt 1+"$USAGELEAPS" ]]
then ADVCPU=$(( $CURRCPU-$USAGELEAPS ))
else ADVCPU=1
fi
fi
#set CPU usage to 50 at start
[ "$COUNTER" -eq 0 ] && ADVCPU=50
#If argument given set it as CPU usage
[ -n "${1}" ] && ADVCPU=$1
#Sometimes puts advised CPU usage above 100%
#meaning that it will take longer to come back down
#to normal percentage. If the script sets it to 0
#it will also go to 100. So here's a warning:
CHECKCPU=$(grep "<cpu_usage_limit>" global_prefs_override.xml | cut -d">" -f2 | cut -d"." -f1)
if [[ "$CHECKCPU" -gt 99-"$USAGELEAPS" || "$CHECKCPU" -lt 2+"$USAGELEAPS" ]]
then echo "Check BOINC's CPU usage limit!"
fi
#Puts out advised CPU usage once at start (^ COUNTER=0)
if [ "$COUNTER" = 0 ]; then
output
COUNTER=1
fi
#Calculates pause for output on screen and to log by remainder
MINUTE=$(date +"%-M")
REMAINDER=$(( $MINUTE % $OUTPUTPAUSE ))
if [ "$REMAINDER" = 0 ] && [ "$MINUTE" != "$OLDMINUTE" ]; then
output
#Save time to compare as to not output more than once in the same minute
OLDMINUTE="$MINUTE"
fi
#Stream EDit line with CPU usage by substituting CURRCPU with ADVCPU
sed '/cpu_usage_limit/ s/'$CURRCPU'/'$ADVCPU'/' <global_prefs_override.xml >tmp/global_prefs_override.xml
#Check temporary backup and copy to original (errors go to output AND into boinctemp.log)
if grep "<cpu_usage_limit>"$ADVCPU"" tmp/global_prefs_override.xml 2>&1>/dev/null | tee -a boinctemp.log
then cp tmp/global_prefs_override.xml global_prefs_override.xml
else echo "Can't edit preferences file. Check your disk." && exit 1
fi
boinccmd --read_global_prefs_override
#if usage is given as argument, exit
[ -n "${1}" ] && exit
sleep "$CHANGEPAUSE"s
done
Hi axl, a little bit of feedback if you don’t mind. For a temp directory I recommend using mktemp command. I also recommend using a “bash trap function” to automatically clean up your tmp on exit. Here’s a sample
Code:
function cleanup_on() {
[ -z "${TMP_DIR%/}" ] || rm -rf "${TMP_DIR}"
}
trap cleanup_on EXIT
export TMP_DIR="$(mktemp -d)"
# now you can write to TMP_DIR and it will auto cleanup on exit
echo stuff > "${TMP_DIR}/file.txt"
do not use both [ ] and [[ ]]. I think [[ ]] is preferred (and good enough).
please use shellcheck to test your script.
I think line 115 will not do what you wish:
Code:
if grep "<cpu_usage_limit>"$ADVCPU"" tmp/global_prefs_override.xml 2>&1>/dev/null | tee -a boinctemp.log
# if will check the return code of tee (not the grep) which is [almost] always 0
# redirection should be written as: grep .... >/dev/null 2>&1
# how do you want to use tee if result was redirected to /dev/null?
# use grep -q if you do not need the result
# also see what shellcheck reports
avoid using grep|cut|sed|head and similar chains, they are usually can be solved with a single command (which is obviously more efficient)
do not use both [ ] and [[ ]]. I think [[ ]] is preferred (and good enough).
please use shellcheck to test your script.
I also recommend shellcheck but to be clear shellcheck does not care about usage of [ ] or [[ ]] or a mix. It does warn you about known bad practices, though. As long as [ ] is not used with more than two expressions (which violates POSIX compatibility) it really doesn’t matter which. If you do use [[ ]] at all then I do recommend being consistent in your usage.
The trap function I gave is also compatible with “set -e”.
Thanks for the feedback. Unless someone reports a compatibility problem I don't care for conventions.
But you're right, pan64. boinctemp.log isn't even created although I had many errors. (Mainly due to connection problems to the BOINC Manager I presume.)
Although it's not needed anymore since I run the script in it's own terminal: How else do I "double log" then (to terminal and a log file) if grep outputs an error?
On further inspection this part might have been why the script sometimes went awry!? Needs more testing.
Sooo after two weeks of letting it run this seemed to be the culprit of it sometimes bugging out, suddenly jumping to 100% with no explanation. Thanks again, pan64. https://gitlab.com/UMLAUTaxl/boincte...685a6a060469e8
But I don't understand what you're saying about redirecting. Is redirecting the problem? I thought it was "just" that the pipe was breaking my if-condition. tee was created to send output into a terminal and a log file. So I would presume it's something like:
Code:
grep foo checkfile | tee -a logfile
Now if I want to check if foo is actually in the checkfile and send error codes into terminal and logfile tee is the way isn't it?
Code:
if grep foo checkfile | tee -a logfile
then echo "checks out"
else echo "failed"
fi
I understand that's not working. But how else would it work?
if you mix stdout and stderr into a logfile (or anywhere else) you cannot separate them any more.
grep can only parse the specified input (either stdin or file[s]), tee can redirect only its input to two [or more] different locations.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.