Zabbix, Wheezy and IPMI

Zabbix requires a newer version of ipmitool than is available on Debian Wheezy (or even sid as of this writing). If you do not have this version, all IPMI functions will silently fail.

I wrote a script that runs on the client machine. The script is run as root, with no parameters, and gets a lot of information from the underlying hardware via the ipmitool (installed). This information is then stored in /tmp/ipmivalues.dat.

Zabbix can query the zabbix agent on this machine and retrieve that information. This is made available by creating the file /etc/zabbix/zabbix_agent.d/ipmi.conf.

Here is the listing for the three files.


# Some zabbix scripts
# you must leave this, otherwise some programs fail to run (because they want a terminal window)
# default, run mon-sat, at 3:00 am
*/5 * * * *       root    /opt/zabbix/


UserParameter=ipmi[*],/opt/zabbix/ $1
UserParameter=ipmi.temp[*],/opt/zabbix/ $1
UserParameter=ipmi.power[*],/opt/zabbix/ $1[*],/opt/zabbix/ $1
UserParameter=discovery.ipmi[*],/opt/zabbix/ discovery $1


#! /usr/bin/perl -w

# script has three modes:
# scriptname [sensor]
#    If sensor entered, return the last reading of the sensor requested from $datafile
#    If no argument passed, read IPMI data and store in $datafile. Must be run as privileged user
# scriptname discovery fan|power|temp
#    If first parameter is constant 'discovery', finds all non-zero sensors of that type

my $command = '/usr/bin/ipmitool sdr'; # command to get sensor readings
my %values; # store the values in this hash for processing
my $datafile = '/tmp/ipmivalues.dat'; # storage of last reading

# Remove leading and trailing blanks from string
sub cleanup {
   my $value = shift;
   $value =~ s/^\s+//;
   $value =~ s/\s+$//;
   return $value;

# read IPMI data via ipmitool command. Must be run as a user who has permission to use the
# ipmitool. Writes data in tab separated list into $datafile.
# assumed to be run via cron job every 5 minutes.
sub readIPMI {
   my @output = ´$command´; # execute ipmitool command and grab the output
   while ( $line = shift @output ) { # for each line returned
      # clean up and split the line, pulling key and value out
      chomp $line;
      my ($label, $value, $status) = split( '\|', $line );
      $label = &cleanup( $label );
      $value = &cleanup( $value );
      ($value, @temp) = split( ' ', $value ); # value is number plus units,
      my $units = join( ' ', @temp );
      $status = &cleanup( $status );
      next if $value eq 'disabled'; # ignore anything disabled
      $label =~ s/ //gi; # remove all internal spaces in label
      $values{$label} = $value; # save the data in hash
   # simply open $datafile and write label\tvalue
   open VALUES,">$datafile" or die "Could not write to $datafile: $!\n";
   foreach my $label ( sort keys %values ) {
      print VALUES "$label\t$values{$label}\n";
   close VALUES;
   ´chmod 666 $datafile´; # be sure we can read if even if run by unpriv user

# retrive one value (based on $key) from $datafile
sub getValue {
   my $key = shift;
   return -1 unless $key;
   # open data file and get line with key in it
   # maybe faster using grep???
   open DATA, "<$datafile" or die "No data to read: $!\n";
   my @lines = grep { /^$key\t/ } ;
   close DATA;
   # clean up line and return the value (second field of tab delim line)
   chomp( $lines[0] );
   ($key,$value) = split ("\t", $lines[0] );
   return $value;

# perform a discovery for Zabbix auto-population on a data file.
# NOTE: file nust exist (ie, we must have been run at least once with
#       no parameters by a privileged user).
# Because Zabbix does not allow us to re-use a command, I had to make
# three different calls using fan|power|temp to get the results
# mainly for the item prototypes, since fan is a real number
# and all three have different units
sub discovery {
   my $sensor = shift; # the sensor we want to find
   my @output;
   # dies horribly if file does not exist
   open DATA, "<$datafile" or die "No data to read: $!\n";
   my @lines = ;
   close DATA;
   # This is really the long way around, going through line by line
   # but discovery should only be run once a day or less, so we'll let
   # it stay sloppy
   foreach $line (@lines) {
      my ($key,$value) = split( "\t", $line );
      if ( $value * 1 && $key =~ m/^($sensor)(.*)/i ) { # if this is of the type of sensor we need
         # record it using the weirdness the data pattern requires
         push @output, '{"{#CLASS}":"' . lc($1) . '","{#NAME}":"' . $key . '"}';
   } # for
   # create the correctly formatted string and return it.
   return '{"data":[' . "\n" . join( ",\n", @output ) . "\n]}";

my $key = shift; # what do we want to do
if ( $key ) { # we have a parameter!
   if (lc ($key) eq 'discovery' ) { # oh, discovery
      print &discovery(shift); # grab next parameter and run discovery
   } else {
      print &getValue( $key ); # anything else, try to get a value for the key
} else { # no  key passed, so we should read instead


Now, on your Zabbix Server, you can call for any of the values found here. I have a template I've made up which I will try to add here in the near future, but if you can not wait, simply cat /tmp/ipmivalues.dat for the keys.

  • Fan speeds are in percent
  • Power is in watts
  • Temperatures are in C (degrees Centigrade).


Last update:
2015-04-16 07:56
Average rating:0 (0 Votes)

You can comment this FAQ

Chuck Norris has counted to infinity. Twice.