LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (http://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   perl script runs fine from command line but fails when invoked by nagios (http://www.linuxquestions.org/questions/linux-newbie-8/perl-script-runs-fine-from-command-line-but-fails-when-invoked-by-nagios-4175430301/)

andrest964 10-03-2012 10:58 AM

perl script runs fine from command line but fails when invoked by nagios
 
Hi Folks,

this is the command line:
[root@monitor libexec]#./check_acc_bk.pl localhost 2
97 Files backed up in the last 2 days

this is the same command invoked by nagios:
[1349278228] EXTERNAL COMMAND: SCHEDULE_FORCED_SVC_CHECK;localhost;Check Account Backups;1349278227
[1349278238] SERVICE ALERT: localhost;Check Account Backups;CRITICAL;HARD;4;No files backed up in the previous 2 days


in nagios commands.cfg:
Code:

# 'check_acc_bk.pl' command definition
define command{
        command_name    check_acc_bk
        command_line    $USER1$/check_acc_bk.pl $HOSTADDRESS$ $ARG1$
        }

then in local.cfg:
Code:

define service{
        use                            local-service        ; Name of service template to use
        host_name                      localhost
        service_description            Check Account Backups
        active_checks_enabled          1
        check_interval                  15
        check_command                  check_acc_bk
        notifications_enabled          0
        }

and in check_acc_bk.pl:
Code:

#!/usr/bin/perl
use strict;
use File::Copy;
$|=1;
my $hostname = $ARGV[0] || die "Usage: (hostname) (days previous)\n";
my $delay = $ARGV[1] || '2' ;
my $status="3";
my $msg="warning failed to run properly \n";
my $retval="0";
$delay = $delay -1;
#my $newfiles = changedfiles($delay);
&changedfiles($delay);
#print "The number of files changed in $delay is $retval\n";
chomp($retval);
#print STDERR"***$retval****in $delay days ******";
        if ($retval ne '0') {
                $status=0;
                $msg="$retval Files backed up in the last $delay days \n";
        } else {
                $delay = $delay +1;
                &changedfiles($delay);
                chomp($retval);
                #print STDERR"***$retval****in $delay days ******";
                #print "The number of files changed in $delay is $newfiles1 \n";
                if ($retval ne '0') {
                        $status=1;
                        $msg="$retval files backed up in the last $delay days \n";
                } else {
                        $status=2;
                        $msg="No files backed up in the  previous $delay days \n";
                }
        }


#=================
# Status Processing
#=================
# 3 UNKNOWN
# 2 CRITICAL
# 1 WARNING
# 0 OK
print $msg;
exit ($status);

#print  "======= subs  =================\n";
sub changedfiles($delay)
{
#      print"delay is $delay\n";
        my $com  = "sudo /usr/bin/find /root/accounting/backup/ -type f -mtime -$delay -print  | wc -l";
        my @lines = `$com`;
        my $num;
        foreach $num (@lines)
        {
                #print "the num = $num\n"; #put in for debugging
                if ($num > 0) {
                $retval = $num;
                }
        }

        return $retval;
}

oh and nagios has sudo rights on /usr/bin/find with no password.


I have another almost identical perl script that checks database file backups and it works fine.

Please help me Obiwan you are my last chance

SecretCode 10-03-2012 12:06 PM

Much easier to read if you use [code][/code] tags.

For debugging purposes can you output the value of $PATH at the beginning of the script? Not that I can see it should make a difference.

What distro are you running this on?

I don't quite understand this subroutine:
Code:

sub changedfiles($delay)
{
#      print"delay is $delay\n";
        my $com  = "sudo /usr/bin/find /root/accounting/backup/ -type f -mtime -$delay -print  | wc -l";
        my @lines = `$com`;
        my $num;
        foreach $num (@lines)
        {
                #print "the num = $num\n"; #put in for debugging
                if ($num > 0) {
                $retval = $num;
                }
        }

        return $retval;
}

Why are you allowing for more than one line to be returned?

andrest964 10-04-2012 12:38 AM

cool thank you for the formatting tip - I was wondering how that was achieved - I'm new to forum participation but have been working with open source since 1994 (was my first Linux install). In those days we used Kermit via a dialup modem (9600 baud) to reach the internet and it was mostly text docs.

I program mostly in Java - Perl is something I use every occasionally (once a year maybe) so please excuse my ignorance. I am only trying to capture one value from the $com command - any suggestions will be appreciated.

The subroutine is to count the number of new and changed files in a directory.

(Centos 5.x) Linux monitor.jagmobile.co.za 2.6.18-308.11.1.el5PAE #1 SMP Tue Jul 10 09:29:33 EDT 2012 i686 i686 i386 GNU/Linux

Nagios Core 3.3.1

perl-5.8.8-38.el5

andrest964 10-04-2012 01:06 AM

I believe the root of the problem is in the system call:
Code:

my $com  = "sudo /usr/bin/find /root/accounting/backup/ -type f -mtime -$delay -print  | wc -l";
however the following is more Nagios friendly
Code:

my $com  = system("sudo /usr/bin/find /root/accounting/backup/ -type f -mtime -$delay -print  | wc -l");
but this causes the subroutine to return 0;
Ideas/examples on how to capture the system calls output to a returnable variable would be great.

andrest964 10-04-2012 02:01 AM

FYI: I just found out that Perl at the command line is not the same as Nagios embedded Perl

SecretCode 10-04-2012 03:39 AM

What are the versions?
Put this in your script as a quick and dirty check
Code:

print `perl -v`
Since you need to capture the output of the wc command, stick with backticks. Also I think system() requires a list not a string, and may not directly support piping.

But what I would suggest is some more error checking ...
Code:

sub changedfiles($delay)
{
#      print"delay is $delay\n";
        my $com  = "sudo /usr/bin/find /root/accounting/backup/ -type f -mtime -$delay -print  | wc -l";
        my @lines = `$com`;
        my $rc = $?;
        if ($rc != 0) { die "Non-zero return code $rc from command"; }
        if ($#lines != 0) { die "Unexpected number of lines ".($#lines+1)." from command"; }

        $retval = $lines[0];
        return $retval;
}


Another thought: is Nagios running in a bash shell? Or at least some shell that supports pipes (|)? If not, it might be necessary to explicitly call bash -c "$com" or something like that.

andrest964 10-04-2012 04:05 AM

It was a permissions issue - solved by:
1) moving the test to a remote machine using nrpe.
2) enabling sudo in nrpe.cfg.
3) configuring sudo to let nagios run perl scripting in libexec without a password.
4) and changing the monitoring machines config to accommodate the remote call.

WOOOOHOOOOO

SecretCode 10-04-2012 09:04 AM

OK, so none of my suggestions then :)
Glad you fixed it!


All times are GMT -5. The time now is 11:29 PM.