Code

Fix Debian bug #425129: SMB guest mode won't work
[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 " ;
62 my $smbclientoptions= $opt_P ? "-p $opt_P " : "";
65 # Options checking
67 ($opt_H) || ($opt_H = shift) || usage("Host name not specified\n");
68 my $host = $1 if ($opt_H =~ /^([-_.A-Za-z0-9 ]+\$?)$/);
69 ($host) || usage("Invalid host: $opt_H\n");
71 ($opt_s) || ($opt_s = shift) || usage("Share volume not specified\n");
72 my $share = $1 if ($opt_s =~ /^([-_.A-Za-z0-9]+\$?)$/);
73 ($share) || usage("Invalid share: $opt_s\n");
75 ($opt_u) || ($opt_u = shift) || ($opt_u = "guest");
76 my $user = $1 if ($opt_u =~ /^([-_.A-Za-z0-9\\]+)$/);
77 ($user) || usage("Invalid user: $opt_u\n");
79 ($opt_p) || ($opt_p = shift) || ($opt_p = "");
80 my $pass = $1 if ($opt_p =~ /(.*)/);
81 $pass = "-N" if ($opt_p eq "");
83 ($opt_w) || ($opt_w = shift) || ($opt_w = 85);
84 my $warn = $1 if ($opt_w =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
85 ($warn) || usage("Invalid warning threshold: $opt_w\n");
87 ($opt_c) || ($opt_c = shift) || ($opt_c = 95);
88 my $crit = $1 if ($opt_c =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
89 ($crit) || usage("Invalid critical threshold: $opt_c\n");
91 # split the type from the unit value
92 #Check $warn and $crit for type (%/M/G) and set up for tests
93 #P = Percent, K = KBytes
94 my $warn_type;
95 my $crit_type;
97 if ($opt_w =~ /^([0-9]+)\%?$/) {
98         $warn = "$1";
99         $warn_type = "P";
100 } elsif ($opt_w =~ /^([0-9]+)k$/) {
101         $warn_type = "K";
102         $warn = $1;
103 } elsif ($opt_w =~ /^([0-9]+)M$/) {
104         $warn_type = "K";
105         $warn = $1 * 1024;
106 } elsif ($opt_w =~ /^([0-9]+)G$/) {
107         $warn_type = "K";
108         $warn = $1 * 1048576;
110 if ($opt_c =~ /^([0-9]+)\%?$/) {
111         $crit = "$1";
112         $crit_type = "P";
113 } elsif ($opt_c =~ /^([0-9]+)k$/) {
114         $crit_type = "K";
115         $crit = $1;
116 } elsif ($opt_c =~ /^([0-9]+)M$/) {
117         $crit_type = "K";
118         $crit = $1 * 1024;
119 } elsif ($opt_c =~ /^([0-9]+)G$/) {
120         $crit_type = "K";
121         $crit = $1 * 1048576;
124 # check if both warning and critical are percentage or size
125 unless( ( $warn_type eq "P" && $crit_type eq "P" ) || ( $warn_type ne "P" && $crit_type ne "P" ) ){
126         $opt_w =~ s/\%/\%\%/g;
127         $opt_c =~ s/\%/\%\%/g;
128         usage("Both warning and critical should be same type- warning: $opt_w critical: $opt_c \n");
131 # verify warning is less than critical
132 if ( $warn_type eq "K") {
133         unless ( $warn > $crit) {
134                 usage("Disk size: warning ($opt_w) should be greater than critical ($opt_c) \n");
135         }
136 }else{
137         unless ( $warn < $crit) {
138                 $opt_w =~ s/\%/\%\%/g;
139                 $opt_c =~ s/\%/\%\%/g;
140                 usage("Percentage: warning ($opt_w) should be less than critical ($opt_c) \n");
141         }
144 my $workgroup = $1 if (defined($opt_W) && $opt_W =~ /(.*)/);
146 my $address = $1 if (defined($opt_a) && $opt_a =~ /(.*)/);
148 # end of options checking
151 my $state = "OK";
152 my $answer = undef;
153 my $res = undef;
154 my @lines = undef;
156 # Just in case of problems, let's not hang Nagios
157 $SIG{'ALRM'} = sub { 
158         print "No Answer from Client\n";
159         exit $ERRORS{"UNKNOWN"};
160 };
161 alarm($TIMEOUT);
163 # Execute an "ls" on the share using smbclient program
164 # get the results into $res
165 if (defined($workgroup)) {
166         if (defined($address)) {
167                 print "$smbclient " . "\/\/$host\/$share" ." $pass -W $workgroup -U $user $smbclientoptions -I $address -c ls\n" if ($verbose);
168                 $res = qx/$smbclient "\/\/$host\/$share" $pass -W $workgroup -U $user $smbclientoptions -I $address -c ls/;
169         } else {
170                 print "$smbclient " . "\/\/$host\/$share" ." $pass -W $workgroup -U $user $smbclientoptions -c ls\n" if ($verbose);
171                 $res = qx/$smbclient "\/\/$host\/$share" $pass -W $workgroup -U $user $smbclientoptions -c ls/;
172         }
173 } else {
174         if (defined($address)) {
175                 print "$smbclient " . "\/\/$host\/$share" ." $pass -U $user $smbclientoptions -I $address -c ls\n" if ($verbose);
176                 $res = qx/$smbclient "\/\/$host\/$share" $pass -U $user $smbclientoptions -I $address -c ls/;
177         } else {
178                 print "$smbclient " . "\/\/$host\/$share" ." $pass -U $user $smbclientoptions -c ls\n" if ($verbose);
179                 $res = qx/$smbclient "\/\/$host\/$share" $pass -U $user $smbclientoptions -c ls/;
180         }
182 #Turn off alarm
183 alarm(0);
185 #Split $res into an array of lines
186 @lines = split /\n/, $res;
188 #Get the last line into $_
189 $_ = $lines[$#lines];
190 #print "$_\n";
192 #Process the last line to get free space.  
193 #If line does not match required regexp, return an UNKNOWN error
194 if (/\s*(\d*) blocks of size (\d*)\. (\d*) blocks available/) {
196         my ($avail) = ($3*$2)/1024;
197         my ($avail_bytes) = $avail;
198         my ($capper) = int(($3/$1)*100);
199         my ($mountpt) = "\\\\$host\\$share";
202         if (int($avail / 1024) > 0) {
203                 $avail = int($avail / 1024);
204                 if (int($avail /1024) > 0) {
205                         $avail = (int(($avail / 1024)*100))/100;
206                         $avail = $avail ."G";
207                 } else {
208                         $avail = $avail ."M";
209                 }
210         } else {
211                 $avail = $avail ."K";
212         }
214 #print ":$warn:$warn_type:\n";
215 #print ":$crit:$crit_type:\n";
216 #print ":$avail:$avail_bytes:$capper:$mountpt:\n";
218         if ((($warn_type eq "P") && (100 - $capper) < $warn) || (($warn_type eq "K") && ($avail_bytes > $warn))) { 
219                 $answer = "Disk ok - $avail ($capper%) free on $mountpt\n";
220         } elsif ((($crit_type eq "P") && (100 - $capper) < $crit) || (($crit_type eq "K") && ($avail_bytes > $crit))) {
221                 $state = "WARNING";
222                 $answer = "WARNING: Only $avail ($capper%) free on $mountpt\n";
223         } else {
224                 $state = "CRITICAL";
225                 $answer = "CRITICAL: Only $avail ($capper%) free on $mountpt\n";
226         }
227 } else {
228         $answer = "Result from smbclient not suitable\n";
229         $state = "UNKNOWN";
230         foreach (@lines) {
231                 if (/(Access denied|NT_STATUS_LOGON_FAILURE)/) {
232                         $answer = "Access Denied\n";
233                         $state = "CRITICAL";
234                         last;
235                 }
236                 if (/(Unknown host \w*|Connection.*failed)/) {
237                         $answer = "$1\n";
238                         $state = "CRITICAL";
239                         last;
240                 }
241                 if (/(You specified an invalid share name|NT_STATUS_BAD_NETWORK_NAME)/) {
242                         $answer = "Invalid share name \\\\$host\\$share\n";
243                         $state = "CRITICAL";
244                         last;
245                 }
246         }
250 print $answer;
251 print "$state\n" if ($verbose);
252 exit $ERRORS{$state};
254 sub print_usage () {
255         print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password> 
256       -w <warn> -c <crit> [-W <workgroup>] [-P <port>] [-a <IP>]\n";
259 sub print_help () {
260         print_revision($PROGNAME,'@NP_VERSION@');
261         print "Copyright (c) 2000 Michael Anthon/Karl DeBisschop
263 Perl Check SMB Disk plugin for Nagios
265 ";
266         print_usage();
267         print "
268 -H, --hostname=HOST
269    NetBIOS name of the server
270 -s, --share=STRING
271    Share name to be tested
272 -W, --workgroup=STRING
273    Workgroup or Domain used (Defaults to \"WORKGROUP\")
274 -a, --address=IP
275    IP-address of HOST (only necessary if HOST is in another network)
276 -u, --user=STRING
277    Username to log in to server. (Defaults to \"guest\")
278 -p, --password=STRING
279    Password to log in to server. (Defaults to an empty password)
280 -w, --warning=INTEGER or INTEGER[kMG]
281    Percent of used space at which a warning will be generated (Default: 85%)
282       
283 -c, --critical=INTEGER or INTEGER[kMG]
284    Percent of used space at which a critical will be generated (Defaults: 95%)
285 -P, --port=INTEGER
286    Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default)
287    
288    If thresholds are followed by either a k, M, or G then check to see if that
289    much disk space is available (kilobytes, Megabytes, Gigabytes)
291    Warning percentage should be less than critical
292    Warning (remaining) disk space should be greater than critical.
294 ";
295         support();