#!/usr/bin/perl

#
# 2010 Thomas Eckhardt (http://tafe.unkelhaeusser.net)
#
# check_cpuavg - Nagios plugin for nrpe
# calculates the average cpu usage since the last call using a temporary file 
#
# v0.1 - Quick&Dirty hack based on check_cpu.sh by Mike Adolphs (http://www.matejunkie.com/)

use strict;

use constant {
	PROCSTAT => "/proc/stat",
	OLDDATAFILE => "/tmp/.check_cpu.var-$>",
	TOOOLDMINUTES => 60
};

# hashes for free, anyone gets one ..
my %STATS_NOW = ();
my %STATS_LAST = ();
my %STATS_DIFF = ();
my %STATS_PERC = ();

sub errout {
   my ($code, $msg) = @_;
   print "UNKNOWN - $msg\n";
   exit($code);
}

sub save_snapshot {   # create OLDDATAFILE
   if ( open (FH, '>', OLDDATAFILE) ) {
      print FH $STATS_NOW{'user'}." ".$STATS_NOW{'nice'}." ".$STATS_NOW{'system'}." ".$STATS_NOW{'idle'}.
	   " ".$STATS_NOW{'iowait'}." ".$STATS_NOW{'irq'}." ".$STATS_NOW{'softirq'}." ".$STATS_NOW{'total'}."\n";
      close FH;
   } else {
      &errout(2, 'Failed to create '.OLDDATAFILE." $!");
   }
}

# read /proc/stat
if ( open (FH, '<', PROCSTAT ) ) { 
   while (<FH>) {
      my $line = $_;
      if ( $line =~ /^cpu\s+(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)\s/ ) {
	$STATS_NOW{'user'} = $1; $STATS_NOW{'nice'} = $2;
	$STATS_NOW{'system'} = $3; $STATS_NOW{'idle'} = $4;
	$STATS_NOW{'iowait'} = $5; $STATS_NOW{'irq'} = $6;
	$STATS_NOW{'softirq'} = $7;
	$STATS_NOW{'total'} = $1 + $2 + $3 + $4 + $5 + $6 + $7;
	#print $STATS_NOW{'user'}." ".$STATS_NOW{'nice'}." ".$STATS_NOW{'system'}." ".$STATS_NOW{'idle'}.
	#	" ".$STATS_NOW{'iowait'}." ".$STATS_NOW{'irq'}." ".$STATS_NOW{'softirq'}."\n";
	last;
      }
   }
   close FH;
} else {
   &errout(1, 'Failed to open '.PROCSTAT." $!");
}

if (keys(%STATS_NOW) < 8) {
   &errout(1, 'wrong data found in '.PROCSTAT);
}

# read last values from OLDDATAFILE
if ( -f OLDDATAFILE && -s OLDDATAFILE) {
   # ignore file if it's too old
   my ($mtime) = (stat(OLDDATAFILE))[10];
   if ( (time() - (TOOOLDMINUTES * 60)) > $mtime) {
	&save_snapshot;
	&errout(1, 'Log too old, restart ..');
   }

   if ( open (FH, '<', OLDDATAFILE) ) { 
      while (<FH>) {
         my $line = $_;
         if ( $line =~ /^(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)\s(\d+)$/ ) {
	   $STATS_LAST{'user'} = $1; $STATS_LAST{'nice'} = $2;
	   $STATS_LAST{'system'} = $3; $STATS_LAST{'idle'} = $4;
	   $STATS_LAST{'iowait'} = $5; $STATS_LAST{'irq'} = $6;
	   $STATS_LAST{'softirq'} = $7;
	   $STATS_LAST{'total'} = $1 + $2 + $3 + $4 + $5 + $6 + $7;
	   #print $STATS_LAST{'user'}." ".$STATS_LAST{'nice'}." ".$STATS_LAST{'system'}." ".$STATS_LAST{'idle'}.
	   #	" ".$STATS_LAST{'iowait'}." ".$STATS_LAST{'irq'}." ".$STATS_LAST{'softirq'}." ".$STATS_LAST{'total'}."\n";
	   last;
         }
      }
      close FH;
   } else {
      &errout(1, 'Failed to open '.OLDDATAFILE." $!");
   }
} else {
   &save_snapshot;
   &errout(1, 'First Run ..');
}

&save_snapshot;

if (keys(%STATS_LAST) < 8) {
   &errout(1, 'wrong data found in '.OLDDATAFILE);
}

# calc diff
foreach my $val ('user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq', 'total') {
   $STATS_DIFF{$val} = $STATS_NOW{$val} - $STATS_LAST{$val};
} 

foreach my $val ('user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq', 'total') {
   $STATS_PERC{$val} = ($STATS_DIFF{$val} / $STATS_DIFF{'total'}) * 100;
} 

# response
printf("OK - CPU-Usage: %3.2f\%", (100 - $STATS_PERC{'idle'}) );

# perfdata
printf(" | 'user'=%3.2f 'nice'=%3.2f 'sys'=%3.2f 'softirq'=%3.2f 'iowait'=%3.2f 'irq'=%3.2f 'idle'=%3.2f\n", 
$STATS_PERC{'user'}, $STATS_PERC{'nice'}, $STATS_PERC{'system'}, $STATS_PERC{'softirq'}, $STATS_PERC{'iowait'},
$STATS_PERC{'irq'}, $STATS_PERC{'idle'});

exit(0);
