Nagios 插件脚本未按预期工作

Nagios 插件脚本未按预期工作

我修改了一个现成的 Nagios 插件 perl 脚本,使其(理论上)根据远程 Linux 服务器上文件的存在与否返回 1 或 0。该脚本运行远程 ssh 会话并以 nagios 用户身份登录。远程 Linux 服务器为该用户设置了私钥,在 bash 命令行上,该脚本按预期工作,但当作为插件运行时,即使文件不存在,它也始终返回“1”(真)。如果能提供一些有关逻辑的帮助或关于 Nagios 中为什么事情没有按预期工作的评论,我将不胜感激。我宁愿使用这种 ssh 登录方法,而不愿在所有 Linux 服务器上安装 nrpe。

从命令行运行(假设远程服务器有一个名为 nagios 的用户并具有有效的私钥):

./check_reboot_required -e ssh -H remote-servers-ip-addr -p 'filename-to-check' -v

哒。

#! /usr/bin/perl -w
#
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
############################################################################

use POSIX;
use strict;
use Getopt::Long;
use lib "/usr/lib/nagios/plugins" ;
use vars qw($host $opt_V $opt_h $opt_v $verbose $PROGNAME $pattern $opt_p $mmin $opt_e $opt_t $opt_H $status $state $msg $msg_q $MAILQ $SHELL $device $used $avail $percent $fs $blocks $CMD $RMTOS);
use utils qw(%ERRORS &print_revision &support &usage );

sub print_help ();
sub print_usage ();
sub process_arguments ();

$ENV{'PATH'}='';
$ENV{'BASH_ENV'}=''; 
$ENV{'ENV'}='';
$PROGNAME = "check_reboot_required";

Getopt::Long::Configure('bundling');
$status = process_arguments();

if ($status){
    print "ERROR: processing arguments\n";
    exit $ERRORS{'UNKNOWN'};
}

$SIG{'ALRM'} = sub {
    print ("ERROR: timed out waiting for $CMD on $host\n");
exit $ERRORS{'WARNING'};
};

$host = $opt_H;
$pattern = $opt_p;

print "Pattern >" . $pattern . "< " if $verbose;
alarm($opt_t);

#$CMD = "/usr/bin/find " . $pattern . " -type f 2>/dev/null| /usr/bin/wc -l";
$CMD = "[ -f " . $pattern . " ] && echo 1 || echo 0";

alarm($opt_t);

## get cmd output from remote system

if (! open (OUTPUT, "$SHELL $host $CMD|" ) ) {
    print "ERROR: could not open $CMD on $host\n";
    exit $ERRORS{'UNKNOWN'};
}

my $perfdata = "";
my $state = "3";
my $msg = "Indeterminate result";
# only first line is relevant in this iteration.
while (<OUTPUT>) {
                my $result = chomp($_);
                $msg = $result;
                print "Shell returned >" . $result . "< length is " . length($result)     . " " if $verbose;
                if ( $result == 1 ) {
                  $msg = "Reboot required (NB: Result still not accurate)" . $result ;
                  $state = $ERRORS{'WARNING'};
                  last;
                } elsif ( $result == 0 ) {
                  $msg = "No reboot required (NB: Result still not accurate) " .    $result ;
              $state = $ERRORS{'OK'};
              last;
            }
            else {
              $msg = "Output received, but it was neither a 1 nor a 0" ;
              last;
            }   

}

close (OUTPUT);
print "$msg | $perfdata\n";
exit $state;

#####################################
#### subs


sub process_arguments(){
    GetOptions
        ("V"   => \$opt_V, "version"    => \$opt_V,
         "v"   => \$opt_v, "verbose"    => \$opt_v,
         "h"   => \$opt_h, "help"   => \$opt_h,
         "e=s" => \$opt_e, "shell=s"    => \$opt_e,
             "p=s" => \$opt_p, "pattern=s"  => \$opt_p,
         "t=i" => \$opt_t, "timeout=i"  => \$opt_t,
         "H=s" => \$opt_H, "hostname=s" => \$opt_H
     );

if ($opt_V) {
    print_revision($PROGNAME,'$Revision: 1.0 $ ');
    exit $ERRORS{'OK'};
}

if ($opt_h) {
    print_help();
    exit $ERRORS{'OK'};
}

if (defined $opt_v ){
    $verbose = $opt_v;
}

    if (defined $opt_e ){
    if ( $opt_e eq "ssh" ) {
        if (-x "/usr/local/bin/ssh") {
        $SHELL = "/usr/local/bin/ssh";
        } elsif ( -x "/usr/bin/ssh" ) {
        $SHELL = "/usr/bin/ssh"; 
        } else {
                    print_usage();
                    exit $ERRORS{'UNKNOWN'};
                }

    } elsif ( $opt_e eq "rsh" ) {
        $SHELL = "/usr/bin/rsh";
    } else {
        print_usage();
                exit $ERRORS{'UNKNOWN'};
    }
    } else {
   print_usage();
       exit $ERRORS{'UNKNOWN'};
}

unless (defined $opt_t) {
    $opt_t = $utils::TIMEOUT ;  # default timeout
}

unless (defined $opt_H) {
    print_usage();
    exit $ERRORS{'UNKNOWN'};
}


return $ERRORS{'OK'};
}

sub print_usage () {
    print "Usage: $PROGNAME -e <shell> -H <hostname> -p <directory/file pattern> [-t <timeout>] [-v verbose]\n";
}

sub print_help () {
print_revision($PROGNAME,'$Revision: 0.1 $');
print "\n";
print_usage();
print "\n";
print "   Checks for the presence of a 'reboot-required' file on a remote host via SSH or RSH\n";
print "-e (--shell)     = ssh or rsh (required)\n";
print "-H (--hostname)  = remote server name (required)";
print "-p (--pattern)   = File pattern for find command (default = /var/run/reboot-required)\n";
print "-t (--timeout)   = Plugin timeout in seconds (default = $utils::TIMEOUT)\n";
print "-h (--help)\n";
print "-V (--version)\n";
print "-v (--verbose)   = debugging output\n";
print "\n\n";
support();
}

答案1

Nagios 运行插件时没有任何 ENV,因此没有 $HOME... 所以它可能找不到 ssh 密钥/身份信息(您可以通过“env -i”运行手动测试来模拟这种情况)。这就是为什么检查_by_ssh有选项可以明确指定此信息。

正如 grifferz 上面评论的那样,你真的应该使用检查_by_ssh,因为您使用的这个 perl 脚本只不过是它的一个(糟糕的)重新实现。

相关内容