Merge pull request #1311 from waja/check_ntp_remove_unused_variables
[monitoring-plugins.git] / plugins-scripts / check_disk_smb.pl
blob98992268df516581095374a227c0f1e7677db0a7
1 #!@PERL@ -w
4 # check_disk.pl <host> <share> <user> <pass> [warn] [critical] [port]
6 # Monitoring 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 FindBin;
28 use lib "$FindBin::Bin";
29 use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
31 sub print_help ();
32 sub print_usage ();
34 $PROGNAME = "check_disk_smb";
36 $ENV{'PATH'}='@TRUSTED_PATH@';
37 $ENV{'BASH_ENV'}='';
38 $ENV{'ENV'}='';
40 Getopt::Long::Configure('bundling');
41 GetOptions
42 ("v" => \$verbose, "verbose" => \$verbose,
43 "P=s" => \$opt_P, "port=s" => \$opt_P,
44 "V" => \$opt_V, "version" => \$opt_V,
45 "h" => \$opt_h, "help" => \$opt_h,
46 "w=s" => \$opt_w, "warning=s" => \$opt_w,
47 "c=s" => \$opt_c, "critical=s" => \$opt_c,
48 "p=s" => \$opt_p, "password=s" => \$opt_p,
49 "u=s" => \$opt_u, "username=s" => \$opt_u,
50 "s=s" => \$opt_s, "share=s" => \$opt_s,
51 "W=s" => \$opt_W, "workgroup=s" => \$opt_W,
52 "H=s" => \$opt_H, "hostname=s" => \$opt_H,
53 "a=s" => \$opt_a, "address=s" => \$opt_a);
55 if ($opt_V) {
56 print_revision($PROGNAME,'@NP_VERSION@'); #'
57 exit $ERRORS{'UNKNOWN'};
60 if ($opt_h) {print_help(); exit $ERRORS{'UNKNOWN'};}
62 my $smbclient = $utils::PATH_TO_SMBCLIENT;
63 $smbclient || usage("check requires smbclient, smbclient not set\n");
64 -x $smbclient || usage("check requires smbclient, $smbclient: $!\n");
66 # Options checking
68 ($opt_H) || ($opt_H = shift @ARGV) || usage("Host name not specified\n");
69 my $host = $1 if ($opt_H =~ /^([-_.A-Za-z0-9 ]+\$?)$/);
70 ($host) || usage("Invalid host: $opt_H\n");
72 ($opt_s) || ($opt_s = shift @ARGV) || usage("Share volume not specified\n");
73 my $share = $1 if ($opt_s =~ /^([-_.A-Za-z0-9 ]+\$?)$/);
74 ($share) || usage("Invalid share: $opt_s\n");
76 defined($opt_u) || ($opt_u = shift @ARGV) || ($opt_u = "guest");
77 my $user = $1 if ($opt_u =~ /^([-_.A-Za-z0-9\\]*)$/);
78 defined($user) || usage("Invalid user: $opt_u\n");
80 defined($opt_p) || ($opt_p = shift @ARGV) || ($opt_p = "");
81 my $pass = $1 if ($opt_p =~ /(.*)/);
83 ($opt_w) || ($opt_w = shift @ARGV) || ($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 @ARGV) || ($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 # Execute the given command line and return anything it writes to STDOUT and/or
92 # STDERR. (This might be useful for other plugins, too, so it should possibly
93 # be moved to utils.pm.)
94 sub output_and_error_of {
95 local *CMD;
96 local $/ = undef;
97 my $pid = open CMD, "-|";
98 if (defined($pid)) {
99 if ($pid) {
100 return <CMD>;
101 } else {
102 open STDERR, ">&STDOUT" and exec @_;
103 exit(1);
106 return undef;
109 # split the type from the unit value
110 #Check $warn and $crit for type (%/M/G) and set up for tests
111 #P = Percent, K = KBytes
112 my $warn_type;
113 my $crit_type;
115 if ($opt_w =~ /^([0-9]+)\%?$/) {
116 $warn = "$1";
117 $warn_type = "P";
118 } elsif ($opt_w =~ /^([0-9]+)k$/) {
119 $warn_type = "K";
120 $warn = $1;
121 } elsif ($opt_w =~ /^([0-9]+)M$/) {
122 $warn_type = "K";
123 $warn = $1 * 1024;
124 } elsif ($opt_w =~ /^([0-9]+)G$/) {
125 $warn_type = "K";
126 $warn = $1 * 1048576;
128 if ($opt_c =~ /^([0-9]+)\%?$/) {
129 $crit = "$1";
130 $crit_type = "P";
131 } elsif ($opt_c =~ /^([0-9]+)k$/) {
132 $crit_type = "K";
133 $crit = $1;
134 } elsif ($opt_c =~ /^([0-9]+)M$/) {
135 $crit_type = "K";
136 $crit = $1 * 1024;
137 } elsif ($opt_c =~ /^([0-9]+)G$/) {
138 $crit_type = "K";
139 $crit = $1 * 1048576;
142 # check if both warning and critical are percentage or size
143 unless( ( $warn_type eq "P" && $crit_type eq "P" ) || ( $warn_type ne "P" && $crit_type ne "P" ) ){
144 $opt_w =~ s/\%/\%\%/g;
145 $opt_c =~ s/\%/\%\%/g;
146 usage("Both warning and critical should be same type- warning: $opt_w critical: $opt_c \n");
149 # verify warning is less than critical
150 if ( $warn_type eq "K") {
151 unless ( $warn > $crit) {
152 usage("Disk size: warning ($opt_w) should be greater than critical ($opt_c) \n");
154 }else{
155 unless ( $warn < $crit) {
156 $opt_w =~ s/\%/\%\%/g;
157 $opt_c =~ s/\%/\%\%/g;
158 usage("Percentage: warning ($opt_w) should be less than critical ($opt_c) \n");
162 my $workgroup = $1 if (defined($opt_W) && $opt_W =~ /(.*)/);
164 my $address = $1 if (defined($opt_a) && $opt_a =~ /(.*)/);
166 # end of options checking
169 my $state = "OK";
170 my $answer = undef;
171 my $res = undef;
172 my $perfdata = "";
173 my @lines = undef;
175 # Just in case of problems, let's not hang the monitoring system
176 $SIG{'ALRM'} = sub {
177 print "No Answer from Client\n";
178 exit $ERRORS{"UNKNOWN"};
180 alarm($TIMEOUT);
182 # Execute a "du" on the share using smbclient program
183 # get the results into $res
184 my @cmd = (
185 $smbclient,
186 "//$host/$share",
187 "-U", "$user%$pass",
188 defined($workgroup) ? ("-W", $workgroup) : (),
189 defined($address) ? ("-I", $address) : (),
190 defined($opt_P) ? ("-p", $opt_P) : (),
191 "-c", "du"
194 print join(" ", @cmd) . "\n" if ($verbose);
195 $res = output_and_error_of(@cmd) or exit $ERRORS{"UNKNOWN"};
197 #Turn off alarm
198 alarm(0);
200 #Split $res into an array of lines
201 @lines = split /\n/, $res;
203 #Get the last line into $_
204 $_ = $lines[$#lines-1];
205 #print "$_\n";
207 #Process the last line to get free space.
208 #If line does not match required regexp, return an UNKNOWN error
209 if (/\s*(\d*) blocks of size (\d*)\. (\d*) blocks available/) {
211 my ($avail_bytes) = $3 * $2;
212 my ($total_bytes) = $1 * $2;
213 my ($occupied_bytes) = $1 * $2 - $avail_bytes;
214 my ($avail) = $avail_bytes/1024;
215 my ($capper) = int(($3/$1)*100);
216 my ($mountpt) = "\\\\$host\\$share";
218 # TODO : why is the kB the standard unit for args ?
219 my ($warn_bytes) = $total_bytes - $warn * 1024;
220 if ($warn_type eq "P") {
221 $warn_bytes = $warn * $1 * $2 / 100;
223 my ($crit_bytes) = $total_bytes - $crit * 1024;
224 if ($crit_type eq "P") {
225 $crit_bytes = $crit * $1 * $2 / 100;
229 if (int($avail / 1024) > 0) {
230 $avail = int($avail / 1024);
231 if (int($avail /1024) > 0) {
232 $avail = (int(($avail / 1024)*100))/100;
233 $avail = $avail ."G";
234 } else {
235 $avail = $avail ."M";
237 } else {
238 $avail = $avail ."K";
241 #print ":$warn:$warn_type:\n";
242 #print ":$crit:$crit_type:\n";
243 #print ":$avail:$avail_bytes:$capper:$mountpt:\n";
244 $perfdata = "'" . $share . "'=" . $occupied_bytes . 'B;'
245 . $warn_bytes . ';'
246 . $crit_bytes . ';'
247 . '0;'
248 . $total_bytes;
250 if ($occupied_bytes > $crit_bytes) {
251 $state = "CRITICAL";
252 $answer = "CRITICAL: Only $avail ($capper%) free on $mountpt";
253 } elsif ( $occupied_bytes > $warn_bytes ) {
254 $state = "WARNING";
255 $answer = "WARNING: Only $avail ($capper%) free on $mountpt";
256 } else {
257 $answer = "Disk ok - $avail ($capper%) free on $mountpt";
259 } else {
260 $answer = "Result from smbclient not suitable";
261 $state = "UNKNOWN";
262 foreach (@lines) {
263 if (/(Access denied|NT_STATUS_LOGON_FAILURE|NT_STATUS_ACCESS_DENIED)/) {
264 $answer = "Access Denied";
265 $state = "CRITICAL";
266 last;
268 if (/(Unknown host \w*|Connection.*failed)/) {
269 $answer = "$1";
270 $state = "CRITICAL";
271 last;
273 if (/(You specified an invalid share name|NT_STATUS_BAD_NETWORK_NAME)/) {
274 $answer = "Invalid share name \\\\$host\\$share";
275 $state = "CRITICAL";
276 last;
282 print $answer;
283 print " | " . $perfdata if ($perfdata);
284 print "\n";
285 print "$state\n" if ($verbose);
286 exit $ERRORS{$state};
288 sub print_usage () {
289 print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password>
290 -w <warn> -c <crit> [-W <workgroup>] [-P <port>] [-a <IP>]\n";
293 sub print_help () {
294 print_revision($PROGNAME,'@NP_VERSION@');
295 print "Copyright (c) 2000 Michael Anthon/Karl DeBisschop
297 Perl Check SMB Disk plugin for monitoring
300 print_usage();
301 print "
302 -H, --hostname=HOST
303 NetBIOS name of the server
304 -s, --share=STRING
305 Share name to be tested
306 -W, --workgroup=STRING
307 Workgroup or Domain used (Defaults to \"WORKGROUP\")
308 -a, --address=IP
309 IP-address of HOST (only necessary if HOST is in another network)
310 -u, --user=STRING
311 Username to log in to server. (Defaults to \"guest\")
312 -p, --password=STRING
313 Password to log in to server. (Defaults to an empty password)
314 -w, --warning=INTEGER or INTEGER[kMG]
315 Percent of used space at which a warning will be generated (Default: 85%)
317 -c, --critical=INTEGER or INTEGER[kMG]
318 Percent of used space at which a critical will be generated (Defaults: 95%)
319 -P, --port=INTEGER
320 Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default)
322 If thresholds are followed by either a k, M, or G then check to see if that
323 much disk space is available (kilobytes, Megabytes, Gigabytes)
325 Warning percentage should be less than critical
326 Warning (remaining) disk space should be greater than critical.
329 support();