#!/usr/bin/perl -w # # Check SAP Availability and Response Time (Packet Round Trip Time) # via SAP load balancing or directly to a specific application server # based on SAP's RFCSDK # # # Copyright (C) 2007 by Herbert Stadler # email: hestadler@gmx.at # License Information: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # ############################################################################ use POSIX; use strict; use Getopt::Long; use lib "."; use lib "/usr/lib/nagios/plugins"; use lib "/usr/lib64/nagios/plugins"; use lib "/usr/local/nagios/libexec"; use utils qw(%ERRORS); my ($opt_version,$opt_help,$opt_verbose); my ($opt_timeout,$opt_license); my ($opt_ashost,$opt_sysnr,$opt_r3name,$opt_mshost,$opt_group); my ($opt_pingcnt,$opt_pingkb,$opt_pingint,$opt_warn,$opt_crit); my ($PROGNAME,$REVISION); my ($state,$msg); use constant RFCPING => "/usr/local/rfcsdk/bin/rfcping"; use constant DEFAULT_TIMEOUT => 30; # please modify if you havn't defined the rfcsdk libraries globally via # /etc/ld.so.conf (ldconfig) $ENV{'LD_LIBRARY_PATH'} = '/usr/local/rfcsdk/lib/'; # return codes of rfcping command my %RFCPING_RC = ( 0 => "OK", 1 => "unrecognized parameter", 2 => "Connect Failure: system down or wrong parameters", 3 => "Timeout from call", 4 => "Unspecified failure: logon/memory/codepage", 255 => "General Error of calling rfcping (libraries missing?)", ); $ENV{'PATH'}=''; $ENV{'BASH_ENV'}=''; $ENV{'ENV'}=''; $PROGNAME = "check_sap_rfcping"; $REVISION = "1.3"; # checking commandline arguments my $arg_status = check_args(); if ($arg_status){ print "ERROR: some arguments wrong\n"; exit $ERRORS{"UNKNOWN"}; } # set alarmhandler for timeout handling $SIG{'ALRM'} = sub { print ("ERROR: plugin timed out after $opt_timeout seconds \n"); exit $ERRORS{"UNKNOWN"}; }; alarm($opt_timeout); # check if command exists and executable flag is set if ( ! -X RFCPING ) { printf ("ERROR: Command %s not found or not executable\n",RFCPING); exit $ERRORS{"UNKNOWN"}; } my $p_rfcping_cmd=""; if ( defined ($opt_mshost)) { $p_rfcping_cmd.=RFCPING." r3name=".$opt_r3name." mshost=".$opt_mshost; } if ( defined ($opt_ashost)) { $p_rfcping_cmd.=RFCPING." sysnr=".$opt_sysnr." ashost=".$opt_ashost; } # and now the optional parameters if (defined $opt_group) { $p_rfcping_cmd.=" group=".$opt_group; } if (defined $opt_pingcnt) { $p_rfcping_cmd.=" ping_cnt=".$opt_pingcnt; } if (defined $opt_pingkb) { $p_rfcping_cmd.=" ping_kb=".$opt_pingkb; } if (defined $opt_pingint) { $p_rfcping_cmd.=" ping_interval=".$opt_pingint; } printf ("\nRFCPING CMD: %s\n",$p_rfcping_cmd) if ($opt_verbose); if ( ! open(CMD, "$p_rfcping_cmd |") ) { print ("ERROR: can not execute $p_rfcping_cmd \n"); exit $ERRORS{"UNKNOWN"}; } # read command output my @t_in=; close(CMD); my $p_rc=$? >> 8; printf ("\nRFCPING RC: %d\n",$p_rc) if ($opt_verbose); if ($p_rc != 0){ print ("ERROR: $RFCPING_RC{$p_rc}\n"); exit $ERRORS{"CRITICAL"}; } my $p_cmdout=join "", @t_in; printf ("\nRFCPING OUTPUT:\n") if ($opt_verbose); printf ("%s",$p_cmdout) if ($opt_verbose); my ($p_minimum_ms,$p_maximum_ms,$p_average_ms,$p_destination); # get round trip times if ( $p_cmdout=~/.*\s+Minimum = (\d+)ms,\s+Maximum = (\d+)ms,\s+Average = (\d+)ms.*/ ) { $p_minimum_ms = $1; $p_maximum_ms = $2; $p_average_ms = $3; } printf ("Min: %d ms, Max: %d ms, Avg: %d ms\n",$p_minimum_ms,$p_maximum_ms,$p_average_ms) if ($opt_verbose); # which SAP destination was it ? if ( $p_cmdout=~/.*Destination\s+(\w+)$.*/ ) { $p_destination = $1; } printf ("Destination: %s\n",$p_destination) if ($opt_verbose); # set default values for progexit $msg = sprintf ("RFCPING OK - No Problems found, AvgRTT=%d ms (%s)",$p_average_ms,$p_destination); $state = $ERRORS{'OK'}; # now we check the response time if (( defined ($opt_warn)) && ( defined ($opt_crit))) { if ( $p_average_ms < $opt_warn ) { $msg = sprintf ("RFCPING OK - No Problems found, AvgRTT=%d ms (%s)",$p_average_ms,$p_destination); $state = $ERRORS{'OK'}; } elsif ( $p_average_ms < $opt_crit ) { $msg = sprintf ("RFCPING WARNING - AvgRTT=%d ms (%s)",$p_average_ms,$p_destination); $state = $ERRORS{'WARNING'}; } else { $msg = sprintf ("RFCPING CRITICAL - AvgRTT=%d ms (%s)",$p_average_ms,$p_destination); $state = $ERRORS{'CRITICAL'}; } } # and now "over and out" print "$msg\n"; exit $state; #--------------------------------------------------------------------------# # S U B R O U T I N E S # #--------------------------------------------------------------------------# sub check_args { Getopt::Long::Configure('bundling'); GetOptions ("V" => \$opt_version, "version" => \$opt_version, "L" => \$opt_license, "license" => \$opt_license, "v" => \$opt_verbose, "verbose" => \$opt_verbose, "h|?" => \$opt_help, "help" => \$opt_help, "t=i" => \$opt_timeout, "timeout=i" => \$opt_timeout, "r=s" => \$opt_r3name, "r3name=s" => \$opt_r3name, "m=s" => \$opt_mshost, "mshost=s" => \$opt_mshost, "a=s" => \$opt_ashost, "ashost=s" => \$opt_ashost, "g=s" => \$opt_group, "group=s" => \$opt_group, "s=i" => \$opt_sysnr, "sysnr=i" => \$opt_sysnr, "n=i" => \$opt_pingcnt, "pingcnt=i" => \$opt_pingcnt, "k=i" => \$opt_pingkb, "pingkb=i" => \$opt_pingkb, "i=i" => \$opt_pingint, "pingint=i" => \$opt_pingint, "w=i" => \$opt_warn, "warn=i" => \$opt_warn, "c=i" => \$opt_crit, "crit=i" => \$opt_crit, ); if ($opt_license) { print_gpl($PROGNAME,$REVISION); exit $ERRORS{'OK'}; } if ($opt_version) { print_revision($PROGNAME,$REVISION); exit $ERRORS{'OK'}; } if ($opt_help) { print_help(); exit $ERRORS{'OK'}; } if ( (! defined($opt_mshost)) && (! defined($opt_ashost))){ print "\nERROR: mshost or ashost not defined\n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } if ( defined($opt_mshost)){ if ( ! defined($opt_r3name)){ print "\nERROR: r3name not defined\n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } } if ( defined($opt_ashost)){ if ( ! defined($opt_sysnr)){ print "\nERROR: sysnr not defined\n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } } if ((defined ($opt_warn)) && (! defined ($opt_crit))) { print "\nERROR: parameter -c not defined\n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } if (( ! defined ($opt_warn)) && ( defined ($opt_crit))) { print "\nERROR: parameter -w not defined\n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } if (( defined ($opt_warn)) && ( defined ($opt_crit))) { if ( $opt_warn >= $opt_crit ) { print "\nERROR: parameter -w greater or equal parameter -c \n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } } unless (defined $opt_timeout) { $opt_timeout = DEFAULT_TIMEOUT; } return $ERRORS{'OK'}; } sub print_usage { print "Usage: $PROGNAME [-h] [-L] [-t timeout] [-v] [-V] [-r r3name] [-s sysnr] [-n pingcount] [-i pinginterval] [-k pingKB] [-w warn] [-c crit] -m mshost | -a ashost \n"; } sub print_help { print_revision($PROGNAME,$REVISION); print "\n"; print_usage(); print "\n"; print " Check SAP Availability and Response Time (Packet Round Trip Time)\n"; print " via SAP load balancing or directly to a specific application server.\n\n"; print " -t (--timeout) Timeout in seconds (default = ",DEFAULT_TIMEOUT,")\n"; print " -m (--mshost) saprouter string to message server\n"; print " -a (--ashost) saprouter string to application server\n"; print " -r (--r3name) SAP SID\n"; print " -s (--sysnr) SAP System number\n"; print " -n (--pingcnt) Number of echo request to send (default=4)\n"; print " -i (--pingint) Number of seconds between interval (default=0)\n"; print " -k (--pingkb) Number of KB to send (default=0)\n"; print " -w (--warn) Warning value of average round trip time in ms\n"; print " -c (--crit) Critical value of average round trip time in ms\n"; print " -h (--help) Help\n"; print " -V (--version) Program version\n"; print " -v (--verbose) Print some useful information\n"; print " -L (--license) Print license information\n"; print "\n"; } sub print_gpl { print <. EOD } sub print_revision { my ($l_prog,$l_revision)=@_; print < and B<-c> options are missing the average round trip time will not be checked. for more information call: check_sap_rfcping -h perldoc check_sap_rfcping =head1 AUTHOR Herbert Stadler, Austria (hestadler@gmx.at) December 2007 This plugin is a contribution to the nagios community. =head1 REQUIRED SOFTWARE RFCSDK from SAP =head1 HOW TO CHECK THE SAP RFC FUNCTIONALITY Please check the functionality with the user under which the nagios service is running (normally nagios: su - nagios) Don't check with root, because of global permissions. Examples of native rfcping commands: =over 2 =item Checking a SPECIFIC APPLICATION SERVER rfcping ashost=/H/sapgate1/S/3297/H/pcintel sysnr=53 =item Checking servers via LOAD BALANCING rfcping r3name=BIN mshost=/H/sapgate1/S/3297/H/hs0311 group=PUBLIC =back rfcping is a command from the SAP RFCSDK toolkit (http://service.sap.com/swdc). Information about where to find the current version of the RFC Library is described in SAP Note 413708. SAP Note 27517 describes the installation of the RFCSDK. SAP is a trademark of SAP AG, Germany. =head1 ADAPTION OF SCRIPT Before calling the script please check some variables which defines the path to rfcping and libraries. use constant RFCPING => "/usr/local/rfcsdk/bin/rfcping"; Please modify the environment variable LD_LIBRARY_PATH if you havn't defined the rfcsdk libraries globally via /etc/ld.so.conf (ldconfig). $ENV{'LD_LIBRARY_PATH'} = '/usr/local/rfcsdk/lib/'; =head1 CONFIGURATION IN NAGIOS Copy this plugin to the nagios plugin installation directory e.g.: /usr/lib(64)/nagios/plugin COMMAND DEFINITION: # "check_sap_rfcping" command definition # checking via Message Server define command{ command_name check_sap_rfcping_ms command_line $USER1$/check_sap_rfcping -m /H/$HOSTADDRESS$ -r $ARG1$ } # checking a specific application server define command{ command_name check_sap_rfcping_as command_line $USER1$/check_sap_rfcping -a /H/$HOSTADDRESS$ -s $ARG1$ } =head1 PLUGIN HISTORY Version 1.3 - 2009-12-04 LD_LIBRARY_PATH added if not globally defined Version 1.2 - 2009-02-17 some new "use lib .." statements Version 1.1 - 2007-12-19 fixed problem with **ePN (Missing right curly or square ...) Version 1.0 - 2007-12-16 first release =head1 COPYRIGHT AND DISCLAIMER Copyright (C) 2007 by Herbert Stadler email: hestadler@gmx.at License Information: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . =cut