Update THANKS file
[monitoring-plugins.git] / plugins-scripts / check_disk_smb.pl
blob0c89db57434c3b46fa6e2361b8be70528287bc1b
1 #!/usr/bin/perl -w
4 # check_disk.pl <host> <share> <user> <pass> [warn] [critical] [port]
6 # Nagios host script to get the disk usage from a SMB share
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
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'};
59 if ($opt_h) {print_help(); exit $ERRORS{'OK'};}
61 my $smbclient = $utils::PATH_TO_SMBCLIENT;
62 $smbclient || usage("check requires smbclient, smbclient not set\n");
63 -x $smbclient || usage("check requires smbclient, $smbclient: $!\n");
65 # Options checking
67 ($opt_H) || ($opt_H = shift @ARGV) || 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 @ARGV) || 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 defined($opt_u) || ($opt_u = shift @ARGV) || ($opt_u = "guest");
76 my $user = $1 if ($opt_u =~ /^([-_.A-Za-z0-9\\]*)$/);
77 defined($user) || usage("Invalid user: $opt_u\n");
79 defined($opt_p) || ($opt_p = shift @ARGV) || ($opt_p = "");
80 my $pass = $1 if ($opt_p =~ /(.*)/);
82 ($opt_w) || ($opt_w = shift @ARGV) || ($opt_w = 85);
83 my $warn = $1 if ($opt_w =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
84 ($warn) || usage("Invalid warning threshold: $opt_w\n");
86 ($opt_c) || ($opt_c = shift @ARGV) || ($opt_c = 95);
87 my $crit = $1 if ($opt_c =~ /^([0-9]{1,2}\%?|100\%?|[0-9]+[kMG])$/);
88 ($crit) || usage("Invalid critical threshold: $opt_c\n");
90 # Execute the given command line and return anything it writes to STDOUT and/or
91 # STDERR. (This might be useful for other plugins, too, so it should possibly
92 # be moved to utils.pm.)
93 sub output_and_error_of {
94 local *CMD;
95 local $/ = undef;
96 my $pid = open CMD, "-|";
97 if (defined($pid)) {
98 if ($pid) {
99 return <CMD>;
100 } else {
101 open STDERR, ">&STDOUT" and exec @_;
102 exit(1);
105 return undef;
108 # split the type from the unit value
109 #Check $warn and $crit for type (%/M/G) and set up for tests
110 #P = Percent, K = KBytes
111 my $warn_type;
112 my $crit_type;
114 if ($opt_w =~ /^([0-9]+)\%?$/) {
115 $warn = "$1";
116 $warn_type = "P";
117 } elsif ($opt_w =~ /^([0-9]+)k$/) {
118 $warn_type = "K";
119 $warn = $1;
120 } elsif ($opt_w =~ /^([0-9]+)M$/) {
121 $warn_type = "K";
122 $warn = $1 * 1024;
123 } elsif ($opt_w =~ /^([0-9]+)G$/) {
124 $warn_type = "K";
125 $warn = $1 * 1048576;
127 if ($opt_c =~ /^([0-9]+)\%?$/) {
128 $crit = "$1";
129 $crit_type = "P";
130 } elsif ($opt_c =~ /^([0-9]+)k$/) {
131 $crit_type = "K";
132 $crit = $1;
133 } elsif ($opt_c =~ /^([0-9]+)M$/) {
134 $crit_type = "K";
135 $crit = $1 * 1024;
136 } elsif ($opt_c =~ /^([0-9]+)G$/) {
137 $crit_type = "K";
138 $crit = $1 * 1048576;
141 # check if both warning and critical are percentage or size
142 unless( ( $warn_type eq "P" && $crit_type eq "P" ) || ( $warn_type ne "P" && $crit_type ne "P" ) ){
143 $opt_w =~ s/\%/\%\%/g;
144 $opt_c =~ s/\%/\%\%/g;
145 usage("Both warning and critical should be same type- warning: $opt_w critical: $opt_c \n");
148 # verify warning is less than critical
149 if ( $warn_type eq "K") {
150 unless ( $warn > $crit) {
151 usage("Disk size: warning ($opt_w) should be greater than critical ($opt_c) \n");
153 }else{
154 unless ( $warn < $crit) {
155 $opt_w =~ s/\%/\%\%/g;
156 $opt_c =~ s/\%/\%\%/g;
157 usage("Percentage: warning ($opt_w) should be less than critical ($opt_c) \n");
161 my $workgroup = $1 if (defined($opt_W) && $opt_W =~ /(.*)/);
163 my $address = $1 if (defined($opt_a) && $opt_a =~ /(.*)/);
165 # end of options checking
168 my $state = "OK";
169 my $answer = undef;
170 my $res = undef;
171 my $perfdata = "";
172 my @lines = undef;
174 # Just in case of problems, let's not hang Nagios
175 $SIG{'ALRM'} = sub {
176 print "No Answer from Client\n";
177 exit $ERRORS{"UNKNOWN"};
179 alarm($TIMEOUT);
181 # Execute a "du" on the share using smbclient program
182 # get the results into $res
183 my @cmd = (
184 $smbclient,
185 "//$host/$share",
186 "-U", "$user%$pass",
187 defined($workgroup) ? ("-W", $workgroup) : (),
188 defined($address) ? ("-I", $address) : (),
189 defined($opt_P) ? ("-p", $opt_P) : (),
190 "-c", "du"
193 print join(" ", @cmd) . "\n" if ($verbose);
194 $res = output_and_error_of(@cmd) or exit $ERRORS{"UNKNOWN"};
196 #Turn off alarm
197 alarm(0);
199 #Split $res into an array of lines
200 @lines = split /\n/, $res;
202 #Get the last line into $_
203 $_ = $lines[$#lines-1];
204 #print "$_\n";
206 #Process the last line to get free space.
207 #If line does not match required regexp, return an UNKNOWN error
208 if (/\s*(\d*) blocks of size (\d*)\. (\d*) blocks available/) {
210 my ($avail_bytes) = $3 * $2;
211 my ($total_bytes) = $1 * $2;
212 my ($occupied_bytes) = $1 * $2 - $avail_bytes;
213 my ($avail) = $avail_bytes/1024;
214 my ($capper) = int(($3/$1)*100);
215 my ($mountpt) = "\\\\$host\\$share";
217 # TODO : why is the kB the standard unit for args ?
218 my ($warn_bytes) = $total_bytes - $warn * 1024;
219 if ($warn_type eq "P") {
220 $warn_bytes = $warn * $1 * $2 / 100;
222 my ($crit_bytes) = $total_bytes - $crit * 1024;
223 if ($crit_type eq "P") {
224 $crit_bytes = $crit * $1 * $2 / 100;
228 if (int($avail / 1024) > 0) {
229 $avail = int($avail / 1024);
230 if (int($avail /1024) > 0) {
231 $avail = (int(($avail / 1024)*100))/100;
232 $avail = $avail ."G";
233 } else {
234 $avail = $avail ."M";
236 } else {
237 $avail = $avail ."K";
240 #print ":$warn:$warn_type:\n";
241 #print ":$crit:$crit_type:\n";
242 #print ":$avail:$avail_bytes:$capper:$mountpt:\n";
243 $perfdata = "'" . $share . "'=" . $occupied_bytes . 'B;'
244 . $warn_bytes . ';'
245 . $crit_bytes . ';'
246 . '0;'
247 . $total_bytes;
249 if ($occupied_bytes > $crit_bytes) {
250 $state = "CRITICAL";
251 $answer = "CRITICAL: Only $avail ($capper%) free on $mountpt";
252 } elsif ( $occupied_bytes > $warn_bytes ) {
253 $state = "WARNING";
254 $answer = "WARNING: Only $avail ($capper%) free on $mountpt";
255 } else {
256 $answer = "Disk ok - $avail ($capper%) free on $mountpt";
258 } else {
259 $answer = "Result from smbclient not suitable";
260 $state = "UNKNOWN";
261 foreach (@lines) {
262 if (/(Access denied|NT_STATUS_LOGON_FAILURE|NT_STATUS_ACCESS_DENIED)/) {
263 $answer = "Access Denied";
264 $state = "CRITICAL";
265 last;
267 if (/(Unknown host \w*|Connection.*failed)/) {
268 $answer = "$1";
269 $state = "CRITICAL";
270 last;
272 if (/(You specified an invalid share name|NT_STATUS_BAD_NETWORK_NAME)/) {
273 $answer = "Invalid share name \\\\$host\\$share";
274 $state = "CRITICAL";
275 last;
281 print $answer;
282 print " | " . $perfdata if ($perfdata);
283 print "\n";
284 print "$state\n" if ($verbose);
285 exit $ERRORS{$state};
287 sub print_usage () {
288 print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password>
289 -w <warn> -c <crit> [-W <workgroup>] [-P <port>] [-a <IP>]\n";
292 sub print_help () {
293 print_revision($PROGNAME,'@NP_VERSION@');
294 print "Copyright (c) 2000 Michael Anthon/Karl DeBisschop
296 Perl Check SMB Disk plugin for Nagios
299 print_usage();
300 print "
301 -H, --hostname=HOST
302 NetBIOS name of the server
303 -s, --share=STRING
304 Share name to be tested
305 -W, --workgroup=STRING
306 Workgroup or Domain used (Defaults to \"WORKGROUP\")
307 -a, --address=IP
308 IP-address of HOST (only necessary if HOST is in another network)
309 -u, --user=STRING
310 Username to log in to server. (Defaults to \"guest\")
311 -p, --password=STRING
312 Password to log in to server. (Defaults to an empty password)
313 -w, --warning=INTEGER or INTEGER[kMG]
314 Percent of used space at which a warning will be generated (Default: 85%)
316 -c, --critical=INTEGER or INTEGER[kMG]
317 Percent of used space at which a critical will be generated (Defaults: 95%)
318 -P, --port=INTEGER
319 Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default)
321 If thresholds are followed by either a k, M, or G then check to see if that
322 much disk space is available (kilobytes, Megabytes, Gigabytes)
324 Warning percentage should be less than critical
325 Warning (remaining) disk space should be greater than critical.
328 support();