Code

Fix Debian bug #478942: Fragile argument passing
[nagiosplug.git] / plugins-scripts / check_disk_smb.pl
1 #!/usr/bin/perl -w
2 #
3 #
4 # check_disk.pl <host> <share> <user> <pass> [warn] [critical] [port]
5 #
6 # Nagios host script to get the disk usage from a SMB share
7 #
8 # Changes and Modifications
9 # =========================
10 # 7-Aug-1999 - Michael Anthon
11 #  Created from check_disk.pl script provided with netsaint_statd (basically
12 #  cause I was too lazy (or is that smart?) to write it from scratch)
13 # 8-Aug-1999 - Michael Anthon
14 #  Modified [warn] and [critical] parameters to accept format of nnn[M|G] to
15 #  allow setting of limits in MBytes or GBytes.  Percentage settings for large
16 #  drives is a pain in the butt
17 # 2-May-2002 - SGhosh fix for embedded perl
18 #
19 #
21 require 5.004;
22 use POSIX;
23 use strict;
24 use Getopt::Long;
25 use vars qw($opt_P $opt_V $opt_h $opt_H $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $opt_a $verbose);
26 use vars qw($PROGNAME);
27 use lib utils.pm ;
28 use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
30 sub print_help ();
31 sub print_usage ();
33 $PROGNAME = "check_disk_smb";
35 $ENV{'PATH'}='';
36 $ENV{'BASH_ENV'}=''; 
37 $ENV{'ENV'}='';
39 Getopt::Long::Configure('bundling');
40 GetOptions
41         ("v"   => \$verbose, "verbose"    => \$verbose,
42          "P=s" => \$opt_P, "port=s"     => \$opt_P,
43          "V"   => \$opt_V, "version"    => \$opt_V,
44          "h"   => \$opt_h, "help"       => \$opt_h,
45          "w=s" => \$opt_w, "warning=s"  => \$opt_w,
46          "c=s" => \$opt_c, "critical=s" => \$opt_c,
47          "p=s" => \$opt_p, "password=s" => \$opt_p,
48          "u=s" => \$opt_u, "username=s" => \$opt_u,
49          "s=s" => \$opt_s, "share=s"    => \$opt_s,
50          "W=s" => \$opt_W, "workgroup=s" => \$opt_W,
51          "H=s" => \$opt_H, "hostname=s" => \$opt_H,
52          "a=s" => \$opt_a, "address=s" => \$opt_a);
54 if ($opt_V) {
55         print_revision($PROGNAME,'@NP_VERSION@'); #'
56         exit $ERRORS{'OK'};
57 }
59 if ($opt_h) {print_help(); exit $ERRORS{'OK'};}
61 my $smbclient = $utils::PATH_TO_SMBCLIENT;
63 # Options checking
65 ($opt_H) || ($opt_H = shift @ARGV) || usage("Host name not specified\n");
66 my $host = $1 if ($opt_H =~ /^([-_.A-Za-z0-9 ]+\$?)$/);
67 ($host) || usage("Invalid host: $opt_H\n");
69 ($opt_s) || ($opt_s = shift @ARGV) || usage("Share volume not specified\n");
70 my $share = $1 if ($opt_s =~ /^([-_.A-Za-z0-9]+\$?)$/);
71 ($share) || usage("Invalid share: $opt_s\n");
73 defined($opt_u) || ($opt_u = shift @ARGV) || ($opt_u = "guest");
74 my $user = $1 if ($opt_u =~ /^([-_.A-Za-z0-9\\]*)$/);
75 defined($user) || usage("Invalid user: $opt_u\n");
77 defined($opt_p) || ($opt_p = shift @ARGV) || ($opt_p = "");
78 my $pass = $1 if ($opt_p =~ /(.*)/);
80 ($opt_w) || ($opt_w = shift @ARGV) || ($opt_w = 85);
81 my $warn = $1 if ($opt_w =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
82 ($warn) || usage("Invalid warning threshold: $opt_w\n");
84 ($opt_c) || ($opt_c = shift @ARGV) || ($opt_c = 95);
85 my $crit = $1 if ($opt_c =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
86 ($crit) || usage("Invalid critical threshold: $opt_c\n");
88 # Execute the given command line and return anything it writes to STDOUT and/or
89 # STDERR.  (This might be useful for other plugins, too, so it should possibly
90 # be moved to utils.pm.)
91 sub output_and_error_of {
92         local *CMD;
93         local $/ = undef;
94         my $pid = open CMD, "-|";
95         if (defined($pid)) {
96                 if ($pid) {
97                         return <CMD>;
98                 } else {
99                         open STDERR, ">&STDOUT" and exec @_;
100                         exit(1);
101                 }
102         }
103         return undef;
106 # split the type from the unit value
107 #Check $warn and $crit for type (%/M/G) and set up for tests
108 #P = Percent, K = KBytes
109 my $warn_type;
110 my $crit_type;
112 if ($opt_w =~ /^([0-9]+)\%?$/) {
113         $warn = "$1";
114         $warn_type = "P";
115 } elsif ($opt_w =~ /^([0-9]+)k$/) {
116         $warn_type = "K";
117         $warn = $1;
118 } elsif ($opt_w =~ /^([0-9]+)M$/) {
119         $warn_type = "K";
120         $warn = $1 * 1024;
121 } elsif ($opt_w =~ /^([0-9]+)G$/) {
122         $warn_type = "K";
123         $warn = $1 * 1048576;
125 if ($opt_c =~ /^([0-9]+)\%?$/) {
126         $crit = "$1";
127         $crit_type = "P";
128 } elsif ($opt_c =~ /^([0-9]+)k$/) {
129         $crit_type = "K";
130         $crit = $1;
131 } elsif ($opt_c =~ /^([0-9]+)M$/) {
132         $crit_type = "K";
133         $crit = $1 * 1024;
134 } elsif ($opt_c =~ /^([0-9]+)G$/) {
135         $crit_type = "K";
136         $crit = $1 * 1048576;
139 # check if both warning and critical are percentage or size
140 unless( ( $warn_type eq "P" && $crit_type eq "P" ) || ( $warn_type ne "P" && $crit_type ne "P" ) ){
141         $opt_w =~ s/\%/\%\%/g;
142         $opt_c =~ s/\%/\%\%/g;
143         usage("Both warning and critical should be same type- warning: $opt_w critical: $opt_c \n");
146 # verify warning is less than critical
147 if ( $warn_type eq "K") {
148         unless ( $warn > $crit) {
149                 usage("Disk size: warning ($opt_w) should be greater than critical ($opt_c) \n");
150         }
151 }else{
152         unless ( $warn < $crit) {
153                 $opt_w =~ s/\%/\%\%/g;
154                 $opt_c =~ s/\%/\%\%/g;
155                 usage("Percentage: warning ($opt_w) should be less than critical ($opt_c) \n");
156         }
159 my $workgroup = $1 if (defined($opt_W) && $opt_W =~ /(.*)/);
161 my $address = $1 if (defined($opt_a) && $opt_a =~ /(.*)/);
163 # end of options checking
166 my $state = "OK";
167 my $answer = undef;
168 my $res = undef;
169 my @lines = undef;
171 # Just in case of problems, let's not hang Nagios
172 $SIG{'ALRM'} = sub { 
173         print "No Answer from Client\n";
174         exit $ERRORS{"UNKNOWN"};
175 };
176 alarm($TIMEOUT);
178 # Execute an "ls" on the share using smbclient program
179 # get the results into $res
180 my @cmd = (
181         $smbclient,
182         "//$host/$share",
183         "-U", "$user%$pass",
184         defined($workgroup) ? ("-W", $workgroup) : (),
185         defined($address) ? ("-I", $address) : (),
186         defined($opt_P) ? ("-p", $opt_P) : (),
187         "-c", "ls"
188 );
190 print join(" ", @cmd) . "\n" if ($verbose);
191 $res = output_and_error_of(@cmd) or exit $ERRORS{"UNKNOWN"};
193 #Turn off alarm
194 alarm(0);
196 #Split $res into an array of lines
197 @lines = split /\n/, $res;
199 #Get the last line into $_
200 $_ = $lines[$#lines];
201 #print "$_\n";
203 #Process the last line to get free space.  
204 #If line does not match required regexp, return an UNKNOWN error
205 if (/\s*(\d*) blocks of size (\d*)\. (\d*) blocks available/) {
207         my ($avail) = ($3*$2)/1024;
208         my ($avail_bytes) = $avail;
209         my ($capper) = int(($3/$1)*100);
210         my ($mountpt) = "\\\\$host\\$share";
213         if (int($avail / 1024) > 0) {
214                 $avail = int($avail / 1024);
215                 if (int($avail /1024) > 0) {
216                         $avail = (int(($avail / 1024)*100))/100;
217                         $avail = $avail ."G";
218                 } else {
219                         $avail = $avail ."M";
220                 }
221         } else {
222                 $avail = $avail ."K";
223         }
225 #print ":$warn:$warn_type:\n";
226 #print ":$crit:$crit_type:\n";
227 #print ":$avail:$avail_bytes:$capper:$mountpt:\n";
229         if ((($warn_type eq "P") && (100 - $capper) < $warn) || (($warn_type eq "K") && ($avail_bytes > $warn))) { 
230                 $answer = "Disk ok - $avail ($capper%) free on $mountpt\n";
231         } elsif ((($crit_type eq "P") && (100 - $capper) < $crit) || (($crit_type eq "K") && ($avail_bytes > $crit))) {
232                 $state = "WARNING";
233                 $answer = "WARNING: Only $avail ($capper%) free on $mountpt\n";
234         } else {
235                 $state = "CRITICAL";
236                 $answer = "CRITICAL: Only $avail ($capper%) free on $mountpt\n";
237         }
238 } else {
239         $answer = "Result from smbclient not suitable\n";
240         $state = "UNKNOWN";
241         foreach (@lines) {
242                 if (/(Access denied|NT_STATUS_LOGON_FAILURE)/) {
243                         $answer = "Access Denied\n";
244                         $state = "CRITICAL";
245                         last;
246                 }
247                 if (/(Unknown host \w*|Connection.*failed)/) {
248                         $answer = "$1\n";
249                         $state = "CRITICAL";
250                         last;
251                 }
252                 if (/(You specified an invalid share name|NT_STATUS_BAD_NETWORK_NAME)/) {
253                         $answer = "Invalid share name \\\\$host\\$share\n";
254                         $state = "CRITICAL";
255                         last;
256                 }
257         }
261 print $answer;
262 print "$state\n" if ($verbose);
263 exit $ERRORS{$state};
265 sub print_usage () {
266         print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password> 
267       -w <warn> -c <crit> [-W <workgroup>] [-P <port>] [-a <IP>]\n";
270 sub print_help () {
271         print_revision($PROGNAME,'@NP_VERSION@');
272         print "Copyright (c) 2000 Michael Anthon/Karl DeBisschop
274 Perl Check SMB Disk plugin for Nagios
276 ";
277         print_usage();
278         print "
279 -H, --hostname=HOST
280    NetBIOS name of the server
281 -s, --share=STRING
282    Share name to be tested
283 -W, --workgroup=STRING
284    Workgroup or Domain used (Defaults to \"WORKGROUP\")
285 -a, --address=IP
286    IP-address of HOST (only necessary if HOST is in another network)
287 -u, --user=STRING
288    Username to log in to server. (Defaults to \"guest\")
289 -p, --password=STRING
290    Password to log in to server. (Defaults to an empty password)
291 -w, --warning=INTEGER or INTEGER[kMG]
292    Percent of used space at which a warning will be generated (Default: 85%)
293       
294 -c, --critical=INTEGER or INTEGER[kMG]
295    Percent of used space at which a critical will be generated (Defaults: 95%)
296 -P, --port=INTEGER
297    Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default)
298    
299    If thresholds are followed by either a k, M, or G then check to see if that
300    much disk space is available (kilobytes, Megabytes, Gigabytes)
302    Warning percentage should be less than critical
303    Warning (remaining) disk space should be greater than critical.
305 ";
306         support();