-1

I have a Perl script that is executed from Nagios XI.

It has two subroutines: SendEmail and SendTraps.

The script works fine when executed manually by passing the required parameters, but it doesn't work when triggered from Nagios. The script gets executed but the subroutines are skipped.

echo is working, but the two subroutines are not working even if the condition is met.

if ( ( $hoststatetype =~ m/HARD/ ) && ( $hoststate =~ m/DOWN/ ) ) {

    `echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;

    sendMail();
    send_trap();
}

Full script here:

use strict;
use warnings;

use Text::CSV;

# Declared all the variables here

# Parsing input arguments

if ( $#ARGV > -1 ) {

   if ( $ARGV[0] eq "-nagiosxi_trigger" ) {

       $prihost       = $ARGV[1];
       $hoststate     = $ARGV[2];
       $hoststatetype = $ARGV[3];
       $hostoutput    = $ARGV[4];
    }
    elsif ( $ARGV[0] eq "-manual_trigger" ) {

        $comment = $ARGV[1];
        $userid  = $ARGV[2];
        $flag    = "Failover-Trigger_Manual";

        print "Maunal Failover triggered with comment: $comment by $userid\n";

        $error_desc = "Maunal Failover triggered with comment: $comment by $userid";

        send_trap();
        sendMail();

        exit 0;
    }
    else {

        print STDERR "Invalid parameter $ARGV[0] \n";

        exit 1;
    }
}
else {

    print STDERR "ERROR:No Arguments Passed.\n";

    exit 1
}

# Check if Host or Service is in Hard/down state

if ( ( $hoststatetype =~ m/HARD/ ) && ( $hoststate =~ m/DOWN/ ) ) {

    `echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;

    sendMail();
    send_trap();
}
elsif ( ( $hoststatetype =~ m/SOFT/ ) && ( $hoststate =~ m/DOWN/ ) ) {

    `echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
}
else {

    `echo "HOST Good, $prihost $hostoutput">>/tmp/failover_log.txt`;
}

# Sub-Routines

sub failover {

    my $csv  = Text::CSV->new({ sep_char => ',' }) or die "Cannot use CSV: ".Text::CSV->error_diag ();;
    my $file = "myxilist";
    my $primary;
    my $secondary;
    #my $xienv;

    my $host = `hostname`;
    chomp $host;
    open( my $data, '<', $file ) or die "Could not open '$file' $!\n";

    while ( my $xi = <$data> ) {
        chomp $xi;

        if ( $csv->parse($xi) ) {

            my @fields = $csv->fields();

            if ( $fields[0] =~ m/$host/ ) {
                $primary   = $fields[1];
                $secondary = $fields[0];
                $xienv     = $fields[2];
            }
            elsif ( $fields[1] =~ m/$host/ ) {
                $primary   = $fields[0];
                $secondary = $fields[1];
                $xienv     = $fields[2];
           }
        }
        else {
            warn "Line could not be parsed: $xi\n";
            exit 1;
        }
    }
my $failovermsg="failover successful from $primary to $secondary server";
return $failovermsg;
}


sub sendMail {

    #  Build the list for mailing out results

    my $mailSubject;
    my $mailID  = "test\@mail.com";
    my @results = failover();

    $mailSubject = "Failover Successful on $xienv instance";

    print "Sending email to $mailID \n";
    `echo "sending Email">>/tmp/failover_log.txt`;

    open MAILX, "|/usr/bin/mailx -s \"$mailSubject\"        $mailID " or die $!;
    print MAILX "@results";
    close MAILX;

    return;
}

sub send_trap {

    # Sending SNMP traps 

    my @results = failover();
    my $trap    = `/usr/bin/snmptrap -v 2c -c public tcp:server:1010 '' MIB::Event Hostname s "$xienv" nSvcDesc s "$flag" nSvcStateID i 2 nSvcOutput s "@results"`;
    return;
}

Any thoughts what could be missing?

  • 1
    So the print part is working, but the subroutines aren't getting called correct? Did you double check the path for them, and that you don't need to pass any variables into the called function? – Flynn Jul 17 '17 at 15:11
  • I'm troubled by this since morning. If i replace the subroutine with the actual commands, that are inside the subroutine, it works. – Lokanadhan Karthik Jul 17 '17 at 15:18
  • But do the subroutines call other declared variables? If so, try inputting the variables between the parenthesis. Like "SendEmail("Firstname","Lastname")" – Flynn Jul 17 '17 at 15:20
  • No arguments needed in the subroutine. – Lokanadhan Karthik Jul 17 '17 at 15:27
  • Ok, so if it isn't printing out errors, maybe your subroutines aren't returning/printing anything? – Flynn Jul 17 '17 at 16:03
  • When i run the script manually, they do print and write to a log file. – Lokanadhan Karthik Jul 17 '17 at 16:12
  • Please show the script in question if you hope that somebody can help you. The snippet you show isn't even valid Perl. On the face of it, perhaps your "Condition" isn't satisfied when the script is called from an application (some variables may not get set as you expect, etc)? – zdim Jul 17 '17 at 18:17
  • Added the script. – Lokanadhan Karthik Jul 17 '17 at 18:54
  • Thank you, much better. (1) Are you certain that `echo` runs? (It _appends_ to a file). (2) As for subroutines, they both take a list return (`@result`) from the `failover()` sub -- but which never `return`s! That is certainly a bug, so add an explicit `return` as needed to `failover()`. (Without it a sub will return the last thing it evaluated, what is bad to rely on.) I don't recall whether `mail` sends email when there's no data and I don't know what `snmptrap` does. (3) Add prints to subs, to track what they do. This should be easy to debug. – zdim Jul 17 '17 at 19:26
  • I'm very certain, echo writes to the file. Failover() already has return explicitly mentioned in the main script (I have removed few lines of code here). In the mail subroutine there's already a echo writing to a file, which too isn't working. – Lokanadhan Karthik Jul 17 '17 at 19:49
  • Alright. Then `sendMail()` _does run_ right after `echo`, and after it the `send_trap()` runs, too. There is no way that these subs just "don't run." Then the question is what happens in those routines, and the first thing to look into is the `failover()`, since they both use it. I don't see "_Failover() already has return explicitly mentioned in the main script_". And I can't tell what `failover()` is supposed to return. But all this is a moot point -- add diagnostic `print` statements to your subs. Print as the sub starts, then after it calls `failover()` ... you must see what's up. – zdim Jul 17 '17 at 21:20
  • Btw, when you post a comment addressing a particular user, please add AT (@) in front of username, like @LokanadhanKarthik. Then that user gets notified of your comment. I only accidentally noticed your last comment. The owner of the question/answer always gets notified, but others may or may not. – zdim Jul 17 '17 at 21:22
  • Which `echo` are you saying is working, and which subroutine calls aren't "working"? There's no difference between the `HARD`, `DOWN` condition and the `SOFT`, `DOWN` condition except that the subroutines aren't called for the latter. The text echoed to the file is identical. – Borodin Jul 17 '17 at 23:14
  • @zdim, i've added the code to the failover sub. That's what my failover sub is returning. Even if my failover sub is not returning anything, sendmail sub should write to a file, when it is called as there's an echo command. But, that is also not working. I'm doing more testing on this one, will keep you posted. – Lokanadhan Karthik Jul 18 '17 at 10:03
  • @Borodin The echo in HARD condition is writing to a file, but the subsequent SUB's are not running. – Lokanadhan Karthik Jul 18 '17 at 10:07
  • In short, if that `echo` runs (and the program doesn't crash there for some reason), then the following `sendMail()` runs as well. So I again suggest to pepper `sendMail()` and `send_trap()` with printing statements (one right as the subs start) to see what is happening. – zdim Jul 18 '17 at 17:28

1 Answers1

0

Issue was in the failover() SubRoutine. I was calling a file "myxilist" that was present in the same directory as the script.

So, the script was working fine when called manually, but when it is triggered from application, script is getting executed from some other directory and the failover sub exits, as it's not able to open the file.

I've provided the full path of the file and the script works fine.

Thank you all for your help.