Ok, so I have exhausted all possible options with this. I cannot figure out why this script fails to compile when trying to divide. The division on line 203 seems to break the whole script. The errors that are displayed are for lines that are 50 some lines below the code. No idea. Please advise.

#!/usr/bin/perl -w


#use strict;
use Getopt::Long qw(:config no_ignore_case_always);
use Net::SNMP;
use Data::Dumper;
use Switch;
use strict;
#use diagnostics;

#define vars for strict
my ($percentUsed,$totalSpace,$totalUsed,$rootSize,$rootUsed,$bootSize,$bootUsed,$volSize,$volUsed,$varSize,$varUsed,$sfSize,$sfUsed,$sqlSize,$sqlUsed,$load_1,$load_5,$load_15);
my ($rootFree,$bootFree,$volFree,$varFree,$sfFree,$sqlFree);
my $host_address;
my $crit;
my $warn;
my $port;
my $type;
my %oids;
my %errors;
my $errors;
my $opt_h;
my %up_interfaces;

#snmp stuff
my $snmpuser = '<user>';
my $snmpauthkey = '<auth key>';
my $snmpprivkey = '<priv key>';
my $snmpprivproto = 'DES';
my $snmpauthproto = 'MD5';

my %STATUS_CODE = ( 'OK' => '0', 'WARNING' => '1', 'CRITICAL' => '2', 'UNKNOWN' => '3' );

my $options = GetOptions ("h|help" => \$opt_h, "H|hostname=s"  => \$host_address, "w=i" => \$warn, "c=i" => \$crit, "p=i" => \$port, "t=s" => \$type);
		
if ( $options == 0 || $opt_h || !$host_address || !$type) {
   print_usage();
   exit $STATUS_CODE{'UNKNOWN'};
}

if (!$port) {
	$port = 161;
}

#sanitize
$host_address =~ s/[^A-Za-z0-9\.]//;

#print $host_address;

my %sensorload = qw(
	load1 1.3.6.1.4.1.2021.10.1.5.1
	load5 1.3.6.1.4.1.2021.10.1.5.2
	load15 1.3.6.1.4.1.2021.10.1.5.3
);
#Probably will want to tweak these...
my %sensorload_errors = qw(
	load1 >1.00
	load5 >1.00
	load15 >1.00
);

my %diskusage = qw(
	RootSize 1.3.6.1.2.1.25.2.3.1.5.31
	RootUsed 1.3.6.1.2.1.25.2.3.1.6.31
	BootSize 1.3.6.1.2.1.25.2.3.1.5.32
	BootUsed 1.3.6.1.2.1.25.2.3.1.6.32
	VolSize 1.3.6.1.2.1.25.2.3.1.5.33
	VolUsed 1.3.6.1.2.1.25.2.3.1.6.33
	VarSize 1.3.6.1.2.1.25.2.3.1.5.34
	VarUsed 1.3.6.1.2.1.25.2.3.1.6.34
	SFSize 1.3.6.1.2.1.25.2.3.1.5.35
	SFUsed 1.3.6.1.2.1.25.2.3.1.6.35
	SQLSize 1.3.6.1.2.1.25.2.3.1.5.36
	SQLUsed 1.3.6.1.2.1.25.2.3.1.6.36
);

#Enter size is KB	
my %disk_errors = qw(
	RootFree <10000
	BootFree <20000
	VolFree <5000000
	VarFree <5000000
	SFFree <5000000
	SQLFree <5000000

);
my %dcinterfaces = qw(
	 eth0 1.3.6.1.2.1.2.2.1.8.4
);
#2 is down, 1 is up for interfaces
my %interfaces = qw(
	eth0 1.3.6.1.2.1.2.2.1.8.8 
	eth1 1.3.6.1.2.1.2.2.1.8.9
	eth2 1.3.6.1.2.1.2.2.1.8.6
	eth3 1.3.6.1.2.1.2.2.1.8.7
	eth4 1.3.6.1.2.1.2.2.1.8.4
	eth5 1.3.6.1.2.1.2.2.1.8.5
);

my %interfaces_oids = qw(
	OERR 1.3.6.1.2.1.2.2.1.20.
	IERR 1.3.6.1.2.1.2.2.1.14.
	BytesR 1.3.6.1.2.1.31.1.1.1.6.
	BytesS 1.3.6.1.2.1.31.1.1.1.10.
);

#This is here for reference, I'm going to shortcut this when i loop the active Ints further below
my %interfaces_errors = qw(
	OERR >0
	IERR >0
);


#Nothing really to edit/tweak past this point.

switch($type) {
	case('interfaces') {  %oids = %interfaces; %errors = %interfaces_errors; }
	case('space') { %oids = %diskusage; ; %errors = %disk_errors;}
	case('load') { %oids = %sensorload; ; %errors = %sensorload_errors;}
	else    { print_usage(); exit $STATUS_CODE{'UNKNOWN'}; }

}


my ($snmpsession, $snmperror) = Net::SNMP->session(
	-hostname => $host_address,
	-version => 'snmpv3',
	-port => $port,
	-username => $snmpuser,
	-timeout => 20,
	-retries => 3,
	-authprotocol => $snmpauthproto,
	-authpassword => $snmpauthkey,
	-privprotocol => $snmpprivproto,
	-privpassword => $snmpprivkey
);
	
if (!defined $snmpsession) {
      printf "ERROR: %s.\n", $snmperror;
      exit $STATUS_CODE{'CRITICAL'};;
}

my $result = $snmpsession->get_request(values %oids);

if($type eq 'space')
{
	my %tmp=%$result;

	foreach my $key(keys %tmp)
	{
		if($key =~ /(5.31$)/) 	
		{
			$rootSize=$tmp{$key};
		}
		elsif($key =~ /(6.31$)/)
		{
			$rootUsed=$tmp{$key};
		}
		elsif($key =~ /(5.32$)/)
		{
			$bootSize=$tmp{$key};
		}
		elsif($key =~ /(6.32$)/)
		{
			$bootUsed=$tmp{$key};
		}
		elsif($key =~ /(5.33$)/)
		{
			$volSize=$tmp{$key};
		}
		elsif($key =~ /(6.33$)/)
		{
			$volUsed=$tmp{$key};
		}
		elsif($key =~ /(5.34$)/)
		{
			$varSize=$tmp{$key};
		}
		elsif($key =~ /(6.34$)/)
		{
			$varUsed=$tmp{$key};
		}
		elsif($key =~ /(5.35$)/)
		{
			$sfSize=$tmp{$key};
		}
		elsif($key =~ /(6.35$)/)
		{
			$sfUsed=$tmp{$key};
		}
		elsif($key =~ /(5.36$)/)
		{
			$sqlSize=$tmp{$key};
		}
		elsif($key =~ /(6.36$)/)
		{
			$sqlUsed=$tmp{$key};
		}
	}
	$totalSpace=$rootSize+$bootSize+$volSize+$varSize+$sfSize+$sqlSize;
	$totalUsed=$rootUsed+$bootUsed+$volUsed+$varUsed+$sfUsed+$sqlUsed;
	$percentUsed=$totalUsed/$totalSpace;
	print "Total space: $totalSpace\n";
	print "Total used: $totalUsed\n";
	print "Percent Used: $percentUsed\n";
	$rootFree=$rootSize-$rootUsed;
	$bootFree=$bootSize-$bootUsed;
	$volFree=$volSize-$volUsed;
	$varFree=$varSize-$varUsed;
	$sfFree=$sfSize-$sfUsed;
	$sqlFree=$sqlSize-$sqlUsed;
	%oids = (); 
	$oids{'RootFree'} = $rootFree;
	$oids{'BootFree'} = $bootFree;
	$oids{'VolFree'} = $volFree;
	$oids{'VarFree'} = $varFree;
	$oids{'SFFree'} = $sfFree;
	$oids{'SQLFree'} = $sqlFree;
}
elsif($type eq 'load')
{
	my %tmp=%$result;
	foreach my $key(keys %tmp)
	{
		if($key =~ /(10.1.5.1$)/)
		{
			$load_1=$tmp{$key};
		}
		if($key =~ /(10.1.5.2$)/)
		{
			$load_5=$tmp{$key};
		}
		if($key =~ /(10.1.5.3$)/)
		{
			$load_15=$tmp{$key};
		}
	}
	%oids = ();
	$oids{'load1'} = $load_1;
	$oids{'load5'} = $load_5;
	$oids{'load15'} = $load_15;
}
#print Dumper($result);
#print Dumper(%oids);


if (!defined $result) {
      printf "ERROR: %s.\n", $snmpsession->error();
      $snmpsession->close();
      exit $STATUS_CODE{'CRITICAL'};
}

#snmp_dispatcher();

switch($type) {
	case('interfaces') {
		
		#Grab all the up interfaces
		while (my ($key,$value) = each(%oids)) {
			#print "--- $value --- ";
			#print "$result->{$value}\n";
			if ($result->{$value} == 1) {
				my @temp = $interfaces{$key} =~ /\.(\d+)$/;
				#print "$temp[0]\n";
				my $oid_tail = $temp[0];
				#sort(%interfaces_oids);
				while (my ($name,$partialoid) = each(%interfaces_oids)) {
				#	print "\t$name\n";
					my $index = $key . '_' . $name;
					#print "$index\n";
					my $complete_oid = $partialoid . $oid_tail;
					#Now jam into hash
					$up_interfaces{$index} = $complete_oid;
					#sort(%up_interfaces);
				}
			}	
		}
	%oids = %up_interfaces;
	#print Dumper(%up_interfaces);
	#undef %up_interfaces;
	#undef %errors;
	#regen the error hash
	foreach (keys %oids) {
		if (/CRC/) { $errors{$_} = '>40'; }
	}
	$result = $snmpsession->get_request(values %oids);
	#print Dumper($result);	
	}
}



$snmpsession->close();

#Loop and compare to the error hash
my $critical = 0;
if($type eq 'space')
{
	while(my ($name,$test) = each(%errors))
	{
		my $value = $oids{$name};
		#print "\t\t\n$value\n";
		my $operator = substr $test, 0, 1;
		my $compare = substr $test, 1;
		$operator = '==' if $operator eq '=';
		my $toeval = "$value $operator $compare";
		#print "\t\t\n$value $operator $compare\nEval: $toeval\n";
		if(eval($toeval))
		{
		#	print "\t\t\n$value $operator $compare\nEval: $toeval\n";
			$critical = 1;
		}
	}
#$rootSize,$rootUsed,$bootSize,$bootUsed,$volSize,$volUsed,$varSize,$varUsed,$sfSize,$sfUsed,$sqlSize,$sqlUsed,$load_1,$load_5,$load_15
%oids = ();
$oids{'RootSize'} = $rootSize;
$oids{'RootUsed'} = $rootUsed;
$oids{'BootSize'} = $bootSize;
$oids{'BootUsed'} = $bootUsed;
$oids{'VolSize'} = $volSize;
$oids{'VolUsed'} = $volUsed;
$oids{'VarSize'} = $varSize;
$oids{'VarUsed'} = $varUsed;
$oids{'SFSize'} = $sfSize;
$oids{'SFUsed'} = $sfUsed;
$oids{'SQLSize'} = $sqlSize;
$oids{'SQLUsed'} = $sqlUsed;

}
elsif($type eq 'load')
{
	while(my ($name,$test) = each(%errors))
	{
		my $value = $oids{$name};
		#print "\t\t\n$value\n";
		my $operator = substr $test, 0, 1;
		my $compare = substr $test, 1;
		$operator = '==' if $operator eq '=';
		my $toeval = "($value/100) $operator $compare";
		#print "\t\t\nEval: $toeval\n";
		if(eval($toeval))
		{
			$critical = 1;
		}
	}

}
elsif($type eq 'interfaces')
{

my $file="/usr/local/nagios/var/$host_address";

#%oids = %interfaces_oids;
	while (my ($name,$test) = each(%errors)) 
	{
		while (my ($name, $oid) = each(%oids))
		{
			if($name =~ /ERR/)
			{
				#print "$name\t$test\n";
				#print $result->{$oids{$name}};	
				my $value = $result->{$oids{$name}};
				#print "$value\n";
				my $operator = substr $test, 0, 1 ;
				my $compare = substr $test, 1;
				$operator = '==' if $operator eq '=';
				my $toeval = "$value $operator $compare";
				unless(-e $file)
				{
					open(STATE, ">>/tmp/$host_address");
					print STATE "$name\t$value\n";
				}
				if (eval($toeval)) 
				{
					#print "$name in error!";
					$critical = 1;
				}
			}
		}
		
	}
close(STATE);
}
#Nagios Output
if ($critical) {
	if ($type eq 'interfaces') {
		print "CRITICAL - Please login to the sensor and verify the errors aren't increasing.";
	}
} else {
	print "OK";
}


#Start Extended Service Info here
print "|";
if($type eq 'space')
{
	while (my ($key,$value) = each(%oids)) 
	{
		my $actvalue=($value*1000);
		print "$key=" . "$actvalue" . ";"
	}
}
elsif($type eq 'load')
{
	while (my ($key,$value) = each(%oids))
	{
		my $actvalue=($value/100);
		print "$key=" . "$actvalue" . ";"
	}
}
else
{
	while(my ($key,$value) = each(%oids)) 
	{
		#print "\n$key\t$value\n";
		#if($type eq 'load') { print "$key=" . ($result->{$value}/100) . ";"; }
		 print "$key=" . $result->{$value} . ";"
	}
}
print "\n";
if ($critical) {
	 exit $STATUS_CODE{'CRITICAL'};
} else {
	 exit $STATUS_CODE{'OK'};
}

sub print_usage {
   print "Usage: check_snmp.pl -H host -t check_type\n\n";
   print "Options:\n";
   print " -H --host STRING or IPADDRESS\n";
   print " -w INTEGER\n";
   print "   warning threshold \n";
   print " -c INTEGER\n";
   print "   critical threshold \n";
   print " -l STRING\n";
   print "   Login name for SSH \n";
   print " -p NUMBER\n";
   print "   port number \n";
   print " -t STRING\n";
   print "   Check type: Valid values - interfaces, space, load\n";

   exit( $STATUS_CODE{"UNKNOWN"} );
}

Recommended Answers

All 8 Replies

Hello,

have your tried moving the two lines to print the totals

#
print "Total space: $totalSpace\n";
#
print "Total used: $totalUsed\n";

up above the calculation so you can make sure neither one came out 0. And if it is a percent shouldn't you also multiply by 100?

Even if I comment out those lines it will still error. I think this is a bug.

Hello,

In my previous comment my question is really what are the values of the two things you are trying to use in the division calculation. Have you checked to make sure you are not somehow dividing by 0 or showing 0% as a result. What are the values of $totalSpace and $totalUsed just prior to the calculation?

If you comment out every reference to the $percentUsed variable does the script compile and run?

I have checked to make sure there's no division by zero going on there. The numbers are large integers.

Why do you say it doesn't compile? When I run it with options -H localhost -t load, for example, it just hangs until I kill it. I don't get any syntax errors indicating it won't compile and no runtime errors such as division by zero, so I can't reproduce the error you are getting. Could you tell us what command-line options you use when you get the division error? Does it work for some hosts and options?

Sorry, I thought the script was just hanging but really it was waiting for 20 * 3 seconds for a response from the localhost server when attempting to create a Net::SNMP->session. If I wait long enough the script ends with ERROR: No response from remote host "localhost" during discovery. The script must have compiled successfully to run and it doesn't give me a division error.

What version of perl are you running? I am getting the error on 5.8.8...other versions run it fine. I am almost certain this is a bug...I am just trying to figure away around it.

What version of perl are you running? I am getting the error on 5.8.8...other versions run it fine. I am almost certain this is a bug...I am just trying to figure away around it.

I'm running version 5.14.2 for linux.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.