-
-
Save geerlingguy/91d4736afe9321cbfc1062165188dda4 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# Raspberry Pi stress CPU temperature measurement script. | |
# | |
# Download this script (e.g. with wget) and give it execute permissions (chmod +x). | |
# Then run it with ./pi-cpu-stress.sh | |
# | |
# NOTE: In recent years, I've switched to using s-tui. See: | |
# https://github.com/amanusk/s-tui?tab=readme-ov-file#options | |
# Variables. | |
test_run=1 | |
test_results_file="${HOME}/cpu_temp_$test_run.log" | |
stress_length="10m" | |
# Verify stress-ng is installed. | |
if ! [ -x "$(command -v stress-ng)" ]; then | |
printf "Error: stress-ng not installed.\n" | |
printf "To install: sudo apt install -y stress-ng\n" >&2 | |
exit 1 | |
fi | |
printf "Logging temperature and throttling data to: $test_results_file\n" | |
# Start logging temperature data in the background. | |
while /bin/true; do | |
line=$(date | tr '\n' '\t') | |
line+=$(vcgencmd measure_temp | tr -d "temp=" | tr -d "'C" | tr '\n' '\t') | |
line+=$(vcgencmd get_throttled | tr -d "throttled=" | tr '\n' '\t') | |
line+=$(vcgencmd measure_clock arm | sed 's/^.*=//') | |
echo $line | |
echo $line >> $test_results_file | |
sleep 5 | |
done & | |
# Store the logging pid. | |
PROC_ID=$! | |
# Stop the logging loop if script is interrupted or when it ends. | |
trap "kill $PROC_ID" EXIT | |
# After 5 minutes, run stress. | |
printf "Waiting 5 minutes for stable idle temperature...\n" | |
printf "Date °C Status CPU Clock\n" | |
sleep 300 | |
printf "Beginning $stress_length stress test...\n" | |
stress-ng -c 4 --timeout $stress_length | |
# Keep logging for 5 more minutes. | |
printf "Waiting 5 minutes to return to idle temperature...\n" | |
sleep 300 | |
printf "Test complete.\n" |
@alwynallan - Ah, good idea to just use the var there instead. Didn't think about the fact that many people run non-Pi-OS distros too!
Better than a /home/${USER}
"half-solution", why not use the standard (and simpler) ${HOME}
?
It would make the script work for any distro and any user, including root
and other service accounts
In addition, attempting to exit the script early with ctrl-c leaves the logging process running - I killed it with
killall
. Not sure if there's an easy fix for that! (I had to exit this way a few times due to the issue above)
This can be solved by setting a trap right after grabbing the pid
:
...
# Store the logging pid.
PROC_ID=$!
# Stop the logging loop if script is interrupted or ends
trap "kill $PROC_ID" EXIT
...
With that you don't even need to manually kill it near end of script, the trap will automatically kill for you when the script ends.
Question: how did you generated the images from the logging data? Is there any nice script for that?
@MestreLion - I think for that I just dumped the CSV into Google Sheets and generated graphs there. Something I'd like to automate more in the future though.
@MestreLion - Also, updated the script to use ${HOME}
and trap
. Thanks for the suggestions!
I also wanted to get the current value from the new PoE+ HAT during a run today, so I added the following above the 'throttle status' section:
# Print the current current (e.g. 536000) and a tab.
cat /sys/devices/platform/rpi-poe-power-supply@0/power_supply/rpi-poe/current_now | tr '\n' '\t' >> $test_results_file;
This outputs a value in microamps.
Great little script! I'm trying to figure out why HTML5 streaming is disappointing on my Pi4b and I thought maybe throttling was the issue. I ran this and temps never report above 71 so I think I'm good, but I also found this: and I'm unclear on whether your script is logging CPU or GPU temps.... or if we can expect them to be pretty much the same...
If that link is correct, you're logging GPU temps and to also log CPU temp
echo temp=$((
cat /sys/class/thermal/thermal_zone0/temp/1000)).0\'C | tr -d "temp=" | tr -d "'C" | tr '\n' '\t' >> $test_results_file;
needs to be added.
@pyro12 - According to the Pi's documentation, measure_temp
"Returns the temperature of the SoC as measured by the on-board temperature sensor." — that seems to be the only reading that really matters for throttling (it's the SoC temp). Are you seeing different numbers when checking thermal_zone0
?
@geerlingguy - Nope. I ran
#!/bin/bash
while true
do
vcgencmd measure_temp | tr -d "temp=" | tr -d "'C" | tr '\n' '\t'
echo temp=$((`cat /sys/class/thermal/thermal_zone0/temp`/1000)).0\'C
sleep 10
done
via SSH and tried various uses of stress-ng and glxgears and the biggest difference I saw was 1.4 C. A curiousity, but I don't think relevant...
Thanks for helping me understand!
Weird! I'm surprised there would be that much of a difference. And now I'm wondering if there are multiple temperature sensors in the SoC :)
I am using following script to record temperature :
from gpiozero import CPUTemperature
from time import sleep, strftime, time
cpu = CPUTemperature()
count=1200 # 20 minutes
with open("/home/pi/temp_log.csv", "a") as log:
while True:
temp = cpu.temperature
log.write("{0},{1}".format(strftime("%Y-%m-%d %H:%M:%S"), str(temp)))
sleep(1)
count -= 1
if count == 0:
break
and using sysbench in a loop:
#!/bin/bash
while true;
do
sysbench --test=cpu --cpu-max-prime=20000 --threads=4 run
sleep 0.1
done
and it works fine.
Question: how did you generated the images from the logging data? Is there any nice script for that?
maybe it can be plot by using matplotlib library.
For those like me that absolutely are newbies with Linux and Pi, this is the command to download the latest version of this file from the CLI:
curl -L https://gist.github.com/geerlingguy/91d4736afe9321cbfc1062165188dda4/raw/ -o _filename.extension_
I updated the script today to output the lines to screen before they're written to the file (helps to also see if the Pi locked up since it will stop printing data). lmk if you'd like that to be a flag so it can be disabled (like -q
for quiet).
Ah, that makes sense. The script can probably be modified to test for whether sudo permissions are required or not, too, with a check near the top to see if
vcgencmd
works.