CPU Temperature

CPU temperature monitoring is vital for administering a system, especially when it comes to server maintenance. With Raspberry Pi being widely used as a home server, completing this tutorial will provide you a way of checking CPU temperature of your Raspberry Pi through a webpage.

Retrieving CPU temperature

First of all, you need to get access to a terminal on your Raspberry Pi. This can be done by creating an SSH connection to it, or by executing LXTerminal application while using Graphic User Interface. Now, run the following command:

/opt/vc/bin/vcgencmd measure_temp

Example output:

temp=40.6'C

Create a Shell script that prints temperature to console

A shell script is a computer program that contains commands otherwise executed one-by-one by a shell (i.e. Bash), also known as a command-line interface/interpreter (CLI).

During this tutorial, two shell scripts will be developed.

The first one will be used to:

The second one will be used to:

Both scripts will be executed by Bash (Bourne Again SHell), a Unix-like shell available on Raspbian.

Take a look at the following code:

#!/bin/bash

TEMP_READING=$(/opt/vc/bin/vcgencmd measure_temp)
TEMP_VALUE=${TEMP_READING:5:4}
echo ${TEMP_VALUE}

What it does:

As you can see, when assigning a value to a variable only the name of the variable is used. On the other hand, using the $ symbol is required to retrieve the value of a variable. $MYVAR has the same effect as ${MYVAR}.

To test the code above store it in a file (i.e. get_temp.sh) and execute it by running: ./get_temp.sh. If you encounter a Permission denied message, run chmod 700 get_temp.sh before executing again.

Create a Round Robin Database

A Round Robin Database (RRD) is a time series database. RRD expects data to be stored in it at given intervals (step). If no value is supplied during an interval, NaN (UNKNOWN) is stored.

Creating a database to store CPU temperature:

rrdtool create cputemp.rrd \
	--start now \
	--step 60 \
	--no-overwrite \
	DS:cpu_temp:GAUGE:120:U:U \
	RRA:AVERAGE:0.5:1:535680

Don’t get confused by \ character. It is used to let the shell know that the following line is part of the current command.

In simple terms, the rrdtool create command above creates a RRD named cputemp.rrd that:

Attention: No action takes place if the database already exists (--no-overwrite).

Documentation of rrdtool create can be found here.

Store data in a RRD

Storing data in a RRD is extremely simple and it is done by rrdtool update command.

The command below stores value 7 in cputemp.rrd:

rrdtool update cputemp.rrd 1412800000:7

1412800000 is the number of seconds since 1970-01-01 00:00:00 UTC (Unix/Epoch time) and you can use the term Timestamp to refer to it.

To find out current time in Epoch time, run date +%s.

The rrdtool update command using current timestamp:

rrdtool update cputemp.rrd $(date +%s):7

Documentation of rrdtool update can be found here.

Graphically represent data stored in a RRD

Fetching data from a RRD and plotting them can be done with rrdtool graph command.

Creating a graph depicting CPU temperature:

rrdtool graph graph.png \
	--start -2h \
	--title "CPU Temperature Log" \
	--vertical-label "Temperature ºC" \
	--width 600 \
	--height 200 \
	--color GRID#C2C2D6 \
	--color MGRID#E2E2E6 \
	--dynamic-labels \
	--grid-dash 1:1 \
	--font TITLE:10 \
	--font UNIT:9 \
	--font LEGEND:8 \
	--font AXIS:8 \
	--font WATERMARK:8 \
	--lazy \
	--watermark "$(date -R)" \
	DEF:cpu_temp=cputemp.rrd:cpu_temp:AVERAGE \
	AREA:cpu_temp#FF0000AA:"RPi CPU" \
	LINE2:cpu_temp#FF0000

Very briefly, the rrdtool graph command above creates a PNG file named graph.png that:

All other options are mainly used for configuring the appearance of the graph. If you are interested in learning more about the available options refer to documentation.

Output of rrdtool graph:

2-Hour Graph

Documentation of rrdtool graph can be found here.

Bash: Output redirection

Running echo "Hello World" will print Hello World to console. In Bash, you can redirect that output to a file.

Executing echo "Hello Raspberry Pi fans!" > hello.txt will create file hello.txt and its contents will be set to match Hello Raspberry Pi fans!. If the file already exists, it will be truncated. Similarily, you can create an HTML file by echo-ing and redirecting output to it.

Another way of redirecting output to a file is the following:

cat > index.html << __EOF__
<!DOCTYPE html>
<head>
	<title>RPi CPU Temperature</title>
	<meta charset="UTF-8">
	<style>
	html {
		text-align: center;
		background: radial-gradient(circle, #DCDFEF, #7886C4);
	}

	body {
		width: 910px;
		margin: auto;
	}
	</style>
</head>
<body>
	<h2>RPi CPU Temperature Graph Report</h2><br>
	<img src="./00-temp-1h.png"  alt="00-temp-1h.png">
	<img src="./01-temp-2h.png"  alt="01-temp-2h.png">
	<img src="./02-temp-4h.png"  alt="02-temp-4h.png">
	<img src="./03-temp-12h.png" alt="03-temp-12h.png">
	<img src="./04-temp-24h.png" alt="04-temp-24h.png">
	<img src="./05-temp-1w.png"  alt="05-temp-1w.png">
	<img src="./06-temp-4w.png"  alt="06-temp-4w.png">
	<img src="./07-temp-24w.png" alt="07-temp-24w.png">
	<img src="./08-temp-1y.png"  alt="08-temp-1y.png">
</body>
</html>
__EOF__

The code above writes the lines between the two __EOF__s to index.html file, which will later be used to display the graphs created by rrdtool graph.

Bash: Conditional execution

During this tutorial you are going to need the following conditionals:

1.

ONE_PATH="/var/www/html"
if [ -d ${ONE_PATH} ]
then
	<commands>
fi

Condition [ -d ${ONE_PATH} ] is assessed to “true” if ONE_PATH exists and is a directory, while [ ! -d ${ONE_PATH} ] is assessed to “false” if ONE_PATH exists and is a directory. As you may have guessed, the exclamation mark is used to invert a condition.

2.

ONE_FILE="/var/www/html/index.html"
if [ -e ${ONE_FILE} ] && [ -s ${ONE_FILE} ]
then
        <commands>
fi

Condition [ -e ${ONE_FILE} ] && [ -s ${ONE_FILE} ] is assessed to “true” if both conditionals beside && are assessed to “true”.

3.

<one-command>
if [ $? -eq 0 ]
then
        <commands>
fi

Condition [ $? -eq 0 ] is assessed to “true” if the exit code of the previous command (i.e. <one-command>) equals 0 (command exited w/o errors).

Bash: Loops and Arrays

Take a look at the following code:

INDEX=0
INTERVALS="1h 2h 4h 12h 24h 1w 4w 24w 1y"
TITLES=('1 Hour' '2 Hour' '4 Hour' '12 Hour' '24 Hour' '1 Week' '1 Month' '6 Month' '1 Year')
for interval in ${INTERVALS}
do
	echo "${INDEX} ${interval} ${TITLES[$INDEX]}"
	((INDEX += 1))
done

Explaining the above code:

Bash: Functions

Function definition:

funcname () {
	<commands>
}

Function call w/o parameters:

funcname

Function call with parameters:

funcname 20 "Pi" "Hello"

In function body, refering to parameters is done by $ followed by a number (i.e. $1 refers to the first parameter).

Bringing it all together

Bringing all the stuff you learned together, results to the following shell scripts:

Execution using Crontab

Crontab allows you to automatically execute a comand or a shell script at given intervals.

Run crontab -e to edit current crontab file. The very first time you will be prompted to choose the editor of your choice.

Assuming that you saved the two shell scripts found above in /root/bin directory, add the following entries at the end of the file:

* * * * * /root/bin/log-cputemp.sh
* * * * * /root/bin/graph-cputemp.sh

in order for both scripts to be executed every minute. Save changes and exit.

Monitoring temperature through a browser

First, you need to now the IP address of your Raspberry Pi by running hostname -I.

Example output:

192.168.1.16

In this case the webpage URL you should visit is: http://192.168.1.16/cpu-temp

Webpage

What next?

While taking a look at log-cputemp.sh and graph-cputemp.sh you may have noticed that in main function there are the following two variables declared:

WWW_DATA="/var/www/html/cpu-temp"
RRD_DATA="/var/www/html/cpu-temp"

Currently, everything is stored under /var/www/html/cpu-temp.

You are free to modify the directory paths at your discretion, as long as WWW_DATA begins with the /var/www/html prefix.

This happens because /var/www/html is the DocumentRoot of Apache. To put it simply, if you request http://192.168.1.16/page.html, Apache will respond with the contents of /var/www/html/page.html.

More information on apache2 can be found here.

Attention: The value of WWW_DIR and RRD_DIR should be the same in both shell scripts.

Note: Apache’s DocumentRoot directory was /var/www in Raspbian Wheezy but is now /var/www/html in Raspbian Jessie.