RPi5B CPU stats and temperatures

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
1 Like