Here's a little script I wrote to generate some CPU stats and temps. Works on RPi5B.
Example:
# temps.sh
CPU temp : 38°C
CPU freq : 2400 MHz ondemand/cpufreq-dt
nvme0n1 temp : 32°C
1.5 GHz 170K |██████████████████████████████████████████████
1.6 GHz 11K |███
1.7 GHz 7.9K |██
1.8 GHz 16K |████
1.9 GHz 15K |████
2.0 GHz 58K |███████████████
2.1 GHz 183K |██████████████████████████████████████████████████
2.2 GHz 30K |████████
2.3 GHz 12K |███
2.4 GHz 37K |██████████
You'll need bash or zsh as well as sed and bc.
temps.sh
#!/bin/bash
cputemp=$(cat /sys/devices/virtual/thermal/thermal_zone0/hwmon1/temp1_input)
freq=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq)
gov=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor)
if [ -d /sys/block/nvme0n1 ]; then
ssd=$(smartctl -a /dev/nvme0n1|grep Temperature: | cut -c37-38)
fi
if [ -f /sys/devices/system/cpu/cpufreq/policy0/scaling_driver ]; then
driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver)
fi
echo "CPU temp : $(( cputemp / 1000 ))°C"
if [ -n "$driver" ]; then
echo "CPU freq : $(( freq / 1000 )) MHz $gov/$driver"
else
echo "CPU freq : $(( freq / 1000 )) MHz $gov"
fi
if [ -d /sys/block/nvme0n1 ]; then
echo "nvme0n1 temp : $ssd°C"
fi
if [ -f /sys/devices/system/cpu/cpufreq/policy0/stats/time_in_state ]; then
echo
# to reset stats
# echo 1 > /sys/devices/system/cpu/cpufreq/policy0/stats/reset
junk="$(mktemp)"
while read -r freq time; do
echo "$freq $(numfmt --to=si --padding=10 "$time")"
done < /sys/devices/system/cpu/cpufreq/policy0/stats/time_in_state > "$junk"
max_value=0
while read -r freq time; do
# Extract the numeric part and unit for time only
numeric=$(echo "$time" | sed -E 's/([0-9.]+)([A-Za-z]+)/\1/')
unit=$(echo "$time" | sed -E 's/([0-9.]+)([A-Za-z]+)/\2/')
# Convert to a comparable number based on unit
case $unit in
K) multiplier=1000 ;;
M) multiplier=1000000 ;;
G) multiplier=1000000000 ;;
T) multiplier=1000000000000 ;;
*) multiplier=1 ;;
esac
value=$(echo "$numeric * $multiplier" | bc)
if [ "$(echo "$value > $max_value" | bc -l)" -eq 1 ]; then
max_value=$value
fi
done < "$junk"
# Set the maximum width of the histogram
max_width=50
# Process each line and create the histogram
while read -r freq time; do
# Convert frequency from Hz to GHz
freq_ghz=$(echo "scale=3; $freq / 1000000" | bc)
# Extract the numeric part and unit for time
numeric=$(echo "$time" | sed -E 's/([0-9.]+)([A-Za-z]+)/\1/')
unit=$(echo "$time" | sed -E 's/([0-9.]+)([A-Za-z]+)/\2/')
# Convert to a comparable number
case $unit in
K) multiplier=1000 ;;
M) multiplier=1000000 ;;
G) multiplier=1000000000 ;;
T) multiplier=1000000000000 ;;
*) multiplier=1 ;;
esac
value=$(echo "$numeric * $multiplier" | bc)
# Calculate the bar length proportional to the maximum value
bar_length=$(echo "$value * $max_width / $max_value" | bc)
# Create the bar
bar=""
i=0
while [ $i -lt "${bar_length%.*}" ]; do
bar="${bar}█"
i=$((i + 1))
done
# Print the frequency in GHz, time, and the bar
printf "%.1f GHz %-10s |%s\n" "$freq_ghz" "$time" "$bar"
done < "$junk"
rm "$junk"
fi