Saturday, November 20, 2010

Dump CPU temperature data to a file in Ubuntu

Update: I've figured out that it makes a lot more sense to have a reading of the CPU load to correlate with the temperature reading, so I've added that too using /usr/bin/uptime.

I have written a very simple Java utility to take readings from the CPU temperature sensors utility (/usr/bin/sensor) and dump it to a CSV file.
Although of fairly limited utility, I just wanted to see how to run a binary from Java and capture its output - and, let's face it, it is a rainy Saturday in Silicon Valley this afternoon and I'd just installed this new CPU cooler and just felt like doing some fuzzying around.
All the code, javadocs and a full working jar are available from the usual place, just remember to create a file under a .sensors directory in your home dir.

Configuring and Running the program
The program itself can be run from the command line with:
$ java -jar sensors_0.1alpha.jar
and a simple properties file looks something like:
# Configuration file for the sensor data storage utility
# Created by M. Massenzio, 2010-11-20

# Default is /usr/bin/sensors, change it here if your installation is different
The data is appended at the end of the CSV file, so it's ok to leave the property unchanged between runs, or even have this run regularly from a cron job (you'll have to do a bit of shell magic to find out it PID and have another job kill it after a given time).

Obviously, an improvement to be to have an additional property configuration to have it terminate after a given amount of time (or a set number of readings).

If you have ideas how to improve this (the obvious next step would be to add a simple JDBC adapter and dump the data on a MySQL database) and/or make changes to the code, please let me know!

The Code
The source code itself is packaged inside the JAR, and consists of a single class, where everything happens, to an extent, just inside the main() method (although, there's a Runnable thrown in to be run as a TimerTask, so it's not as banal as it sounds!).

Executing an external command

Running a Process from inside Java code, is a simple matter of executing:
String sensorProcessLocation = System.getProperty("sensors.command", 
Process p = Runtime.getRuntime().exec(sensorProcessLocation);
LineNumberReader reader = new LineNumberReader(
    new InputStreamReader(p.getInputStream()));
The last lines captures the output from the process (I know, blatantly confusing) and you can then use to 'pipe' its output into your code for processing.

The RegEx to parse the output
Although the output from sensors would be pretty easy to parse 'by hand' I thought it much more elegant to use a Regular Expression, and also throw in the concept 'capturing groups' to have an orderly output (although, it's a safe bet sensors will consistently output the temperature readings in 'sorted cores order'):
REGEX = "Core([01]).*\\+([0-9.]*).*"

will correctly parse output from the version of sensors installed on my distro (Ubuntu 9.10, Karmic Koala):

$ lsb_release -a
   No LSB modules are available.
   Distributor ID: Ubuntu
   Description: Ubuntu 9.10
   Release: 9.10
   Codename: karmic
 $ sensors
   Adapter: PCI adapter
   Core0 Temp:  +42.0°C                                    
   Core1 Temp:  +39.0°C

This is the code that parses the output from sensors, and puts the correct reading in the respective core's array slot:

Pattern p = Pattern.compile(System.getProperty("", 
  Matcher m = p.matcher(reading);
  if (m.matches()) {
    int core = Integer.parseInt(;
    if (core < coreTemps.length) {
       coreTemps[core] = Float.parseFloat(;
The rest of the code (available inside the Jar to download, alongside with the javadoc in the /apidocs folder) is pretty much simple housekeeping.

No comments:

Post a Comment