[Nagiosplug-devel] Plugin to check SMB shares
Andreas Baetz
lac01 at web.de
Mon Jan 13 22:24:02 CET 2003
Hi,
I have written a nagios plugin in Perl that checks for
the availability of shares and printers an Windows
or Samba Servers using smbclient.
It uses utils.pm from sghosh and is based on an example
plugin code from ??. (If someone knows the author of the example
code, please tell me or include the credits yourself).
I first postet this mail in nagios-devel, but I feel this list
is more appropriate.
There is a plugin called "check_disk_smb", which also
checks smb shares, but it is aimed at checking
the free space on one share, whereas my check tests the
existence of multiple shares/printers in one call.
I'm using it for a while now in production.
If you like, you can verify/review/modify/test it, and possibly
include it in the main plugin distribution, if there is an interest.
License is same as perl.
Andreas Baetz
Here it comes (check_smb_shares.pl):
#######################################################
#!/usr/bin/perl -w
# Copyright 2003 Andreas Baetz (andreas.baetz at herma.de)
# License: same licence as Perl itself
# this script checks for smb shares on a windows server
# the shares to check for are given with parameter "check"
# and can be Disks or Printers, depending on Parameter "type"
# type maybe "Disk" or "Printer"
# Return codes:
# "OK" if all tested shares are there
# "WARNING" if there are smbclient errors
# "CRITICAL"if at least one share is not listed at the queried server
# "UNKNOWN" if it doesn't get a response from the server within timeout
# example:
# check_smbshares.pl -H server -D Domain -U user -P Password -T type -C share1,share2
# Caution:
# smbclient doesn't display share names with a length of more than 12 characters
#$Log: check_smbshares.pl,v $
#Revision 1.1 2003/01/09 13:07:38 baz
#Initial revision
#
#It's the script's exit code that Netsaint interprets as a status, viz (from
# utils.pm):
# 'DEPENDENT'=>4,
# 'UNKNOWN'=>3,
# 'OK'=>0,
# 'WARNING'=>1,
# 'CRITICAL'=>2
# Anything you send to STDOUT (e.g. prints) gets added as explanatory message
# text when run from Netsaint (thus everything except help/usage should be
# short).
#
# If you will ever share your plugin (or just as good coding style, anyway),
# there are a few other conventions to follow though. There is a FAQ about
# this on the website somewhere, but the easiest way is probably to take an
# existing plugin and just modify the "business logic" (and the help text!).
# There is a also a little module, utils.pm, which has a few convenience
# functions but is mainly useful for saying:
# exit $ERRORS{'CRITICAL'};
# instead of having to memorise the status codes. (Makes for much more
# readable code!)
#
use vars qw($PROGNAME $runtimedir);
BEGIN {
$PROGNAME=$0;
$runtimedir='.';
if ($0 =~ m/^(.*?)[\/\\]([^\/\\]+)$/) {
$runtimedir = $1;
$PROGNAME = $2;
}
}
use strict;
use lib $runtimedir;
use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
use Getopt::Long;
my ($opt_C,$opt_H,$opt_t,$opt_P,$opt_U,$opt_D,$opt_T);
Getopt::Long::Configure('bundling', 'no_ignore_case');
GetOptions
("V|version" => \&version,
"h|help" => \&help,
"H|host=s" => \$opt_H,
"U|user=s" => \$opt_U,
"P|password=s" => \$opt_P,
"D|domain=s" => \$opt_D,
"T|type=s" => \$opt_T,
"C|check=s" => \$opt_C,
"t|timeout=i" => \$opt_t);
# ??? Maybe do some bounds checking on params here, with
# exit $ERRORS{'UNKNOWN'} if they don't make sense.
$opt_t = 10 unless defined $opt_t; # Set a default
$opt_T = 'Disk' unless defined $opt_T; # Set a default
$opt_D = '' unless defined $opt_D; # Set a default
$opt_C = '' unless defined $opt_C; # Set a default
$opt_U = 'nagios' unless defined $opt_U; # Set a default
$opt_P = '' unless defined $opt_P; # Set a default
help() unless $opt_H; # Required param
help() unless $opt_D; # Required param
help() unless $opt_P; # Required param
help() unless $opt_C; # Required param
#Just in case of problems, let's not hang NetSaint
$SIG{'ALRM'} = sub {
print "No Answer from Host\n";
exit $ERRORS{"UNKNOWN"};
};
alarm $opt_t;
&queryserver($opt_H,$opt_U,$opt_P,$opt_D,$opt_T,$opt_C);
alarm 0;
######################################################################
############## This subroutine does the actual checking ##############
######################################################################
sub queryserver
{
# asks a server about it's shares and returns the nagios status
# arg1: server
# arg2: user
# arg3: password
# arg4: domain
# arg5: Type
# arg5: checks
my @found;
my $server=shift;
my $user=shift;
my $password=shift;
my $domain=shift;
my $type=shift;
my $checks=shift;
if (!$checks) {
print "Error: to few parameters: Host, Password, Checks needed";
exit $ERRORS{'UNKNOWN'};
}
my @checks=split(',',$checks);
my $cmd="/usr/bin/smbclient -L $server -U $user%$password -W $domain";
my $res=open IN,"$cmd 2>&1 |";
if (!$res) {
print "Error: cannot run command $cmd\n";
exit $ERRORS{'UNKNOWN'};
}
while (<IN>) {
s/\n//g;
# something wrong:
if ((/session setup failed/i) || (/Connection to .* failed/i)) {
close IN;
print "$_\n";
exit $ERRORS{'WARNING'};
}
# print ">$_<\n";
if (/^\s+(\S+)\s+$type/g) {
push (@found,$1);
}
}
close IN;
my $problem=0;
my $next=0;
foreach (@checks) {
my $check=$_;
my $ok=0;
foreach (@found) {
my $found=$_;
my $lookfor=$found;
my $checkfor=$check;
$lookfor=~s/\$/#/g;
$checkfor=~s/\$/#/g;
if ($checkfor=~/^$lookfor$/i) {
print " - " if ($next++);
print "$found: exists";
$ok=1;
}
}
if (!$ok) {
print " - " if ($next++);
print "$check: missing";
$problem=1;
}
}
print "\n";
if ($problem) {
exit $ERRORS{'CRITICAL'};
} else {
exit $ERRORS{'OK'};
}
}
######################################################################
sub print_help() {
print_revision($PROGNAME,'$Revision: 1.1 $ ');
print_usage();
print <<END_HELP;
-h, --help Display this message.
-V, --version Print version numbers and license information
-H, --host Host to connect to
-t, --timeout timeout
-U, --user user to connect as
-P, --password password to use
-D, --domain Domain
-P, --password Type of query (Disk or Printer)
-C, --check checked shares or printers
END_HELP
}
######################################################################
sub print_usage {
print "$PROGNAME -H host [-U user] -P password -D Domain -T type (Disk|Printer) -C check1[,check2] [-t timeout]\n";
print "$PROGNAME [-h | --help]\n";
print "$PROGNAME [-V | --version]\n";
}
######################################################################
sub version {
print_revision($PROGNAME,'$Revision: 1.1 $ ');
exit $ERRORS{'OK'};
}
######################################################################
sub help {
print_help();
# The example had exit OK, but that hides mangled parameters
exit $ERRORS{'UNKNOWN'};
}
More information about the Devel
mailing list