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 # $Id$
20 #
22 require 5.004;
23 use POSIX;
24 use strict;
25 use Getopt::Long;
26 use vars qw($opt_P $opt_V $opt_h $opt_H $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $verbose);
27 use vars qw($PROGNAME);
28 use lib utils.pm ;
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'}='';
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);
54 if ($opt_V) {
55 print_revision($PROGNAME,'$Revision$'); #'
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 =~ /(.*)/);
82 ($opt_w) || ($opt_w = shift) || ($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) || ($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 # check if both warning and critical are percentage or size
91 unless( ( ($opt_w =~ /([0-9]){1,2}$/ ) && ($opt_c =~ /([0-9]){1,2}$/ ) )|| (( $opt_w =~ /[kMG]/ ) && ($opt_c =~ /[kMG]/) ) ){
92 usage("Both warning and critical should be same type- warning: $opt_w critical: $opt_c \n");
93 }
95 # verify warning is less than critical
96 if ( $opt_w =~ /[kMG]/) {
97 unless ( $warn > $crit) {
98 usage("Disk size: warning ($opt_w) should be greater than critical ($opt_c) \n");
99 }
100 }else{
101 unless ( $warn < $crit) {
102 usage("Percentage: warning ($opt_w) should be less than critical ($opt_c) \n");
103 }
104 }
106 my $workgroup = $1 if (defined($opt_W) && $opt_W =~ /(.*)/);
108 # end of options checking
111 my $state = "OK";
112 my $answer = undef;
113 my $res = undef;
114 my @lines = undef;
116 # Just in case of problems, let's not hang Nagios
117 $SIG{'ALRM'} = sub {
118 print "No Answer from Client\n";
119 exit $ERRORS{"UNKNOWN"};
120 };
121 alarm($TIMEOUT);
123 # Execute an "ls" on the share using smbclient program
124 # get the results into $res
125 if (defined($workgroup)) {
126 $res = qx/$smbclient \/\/$host\/$share -W $workgroup -U $user%$pass $smbclientoptions -c ls/;
127 } else {
128 print "$smbclient " . "\/\/$host\/$share" ." $pass -U $user $smbclientoptions -c ls\n" if ($verbose);
129 $res = qx/$smbclient \/\/$host\/$share -U $user%$pass $smbclientoptions -c ls/;
130 }
131 #Turn off alarm
132 alarm(0);
134 #Split $res into an array of lines
135 @lines = split /\n/, $res;
137 #Get the last line into $_
138 $_ = $lines[$#lines];
139 #print "$_\n";
141 #Process the last line to get free space.
142 #If line does not match required regexp, return an UNKNOWN error
143 if (/\s*(\d*) blocks of size (\d*)\. (\d*) blocks available/) {
145 my ($avail) = ($3*$2)/1024;
146 my ($avail_bytes) = $avail;
147 my ($capper) = int(($3/$1)*100);
148 my ($mountpt) = "\\\\$host\\$share";
150 #Check $warn and $crit for type (%/M/G) and set up for tests
151 #P = Percent, K = KBytes
152 my $warn_type;
153 my $crit_type;
155 if ($opt_w =~ /^([0-9]+$)/) {
156 $warn_type = "P";
157 } elsif ($opt_w =~ /^([0-9]+)k$/) {
158 $warn_type = "K";
159 $warn = $1;
160 } elsif ($opt_w =~ /^([0-9]+)M$/) {
161 $warn_type = "K";
162 $warn = $1 * 1024;
163 } elsif ($opt_w =~ /^([0-9]+)G$/) {
164 $warn_type = "K";
165 $warn = $1 * 1048576;
166 }
167 if ($opt_c =~ /^([0-9]+$)/) {
168 $crit_type = "P";
169 } elsif ($opt_c =~ /^([0-9]+)k$/) {
170 $crit_type = "K";
171 $crit = $1;
172 } elsif ($opt_c =~ /^([0-9]+)M$/) {
173 $crit_type = "K";
174 $crit = $1 * 1024;
175 } elsif ($opt_c =~ /^([0-9]+)G$/) {
176 $crit_type = "K";
177 $crit = $1 * 1048576;
178 }
180 if (int($avail / 1024) > 0) {
181 $avail = int($avail / 1024);
182 if (int($avail /1024) > 0) {
183 $avail = (int(($avail / 1024)*100))/100;
184 $avail = $avail ."G";
185 } else {
186 $avail = $avail ."M";
187 }
188 } else {
189 $avail = $avail ."K";
190 }
192 #print ":$warn:$warn_type:\n";
193 #print ":$crit:$crit_type:\n";
194 #print ":$avail:$avail_bytes:$capper:$mountpt:\n";
196 if ((($warn_type eq "P") && (100 - $capper) < $warn) || (($warn_type eq "K") && ($avail_bytes > $warn))) {
197 $answer = "Disk ok - $avail ($capper%) free on $mountpt\n";
198 } elsif ((($crit_type eq "P") && (100 - $capper) < $crit) || (($crit_type eq "K") && ($avail_bytes > $crit))) {
199 $state = "WARNING";
200 $answer = "WARNING: Only $avail ($capper%) free on $mountpt\n";
201 } else {
202 $state = "CRITICAL";
203 $answer = "CRITICAL: Only $avail ($capper%) free on $mountpt\n";
204 }
205 } else {
206 $answer = "Result from smbclient not suitable\n";
207 $state = "UNKNOWN";
208 foreach (@lines) {
209 if (/(Access denied|NT_STATUS_LOGON_FAILURE)/) {
210 $answer = "Access Denied\n";
211 $state = "CRITICAL";
212 last;
213 }
214 if (/(Unknown host \w*|Connection.*failed)/) {
215 $answer = "$1\n";
216 $state = "CRITICAL";
217 last;
218 }
219 if (/(You specified an invalid share name|NT_STATUS_BAD_NETWORK_NAME)/) {
220 $answer = "Invalid share name \\\\$host\\$share\n";
221 $state = "CRITICAL";
222 last;
223 }
224 }
225 }
228 print $answer;
229 print "$state\n" if ($verbose);
230 exit $ERRORS{$state};
232 sub print_usage () {
233 print "Usage: $PROGNAME -H <host> -s <share> -u <user> -p <password>
234 -w <warn> -c <crit> [-W <workgroup>] [-P <port>]\n";
235 }
237 sub print_help () {
238 print_revision($PROGNAME,'$Revision$');
239 print "Copyright (c) 2000 Michael Anthon/Karl DeBisschop
241 Perl Check SMB Disk plugin for Nagios
243 ";
244 print_usage();
245 print "
246 -H, --hostname=HOST
247 NetBIOS name of the server
248 -s, --share=STRING
249 Share name to be tested
250 -W, --workgroup=STRING
251 Workgroup or Domain used (Defaults to \"WORKGROUP\")
252 -u, --user=STRING
253 Username to log in to server. (Defaults to \"guest\")
254 -p, --password=STRING
255 Password to log in to server. (Defaults to an empty password)
256 -w, --warning=INTEGER or INTEGER[kMG]
257 Percent of used space at which a warning will be generated (Default: 85%)
259 -c, --critical=INTEGER or INTEGER[kMG]
260 Percent of used space at which a critical will be generated (Defaults: 95%)
261 -P, --port=INTEGER
262 Port to be used to connect to. Some Windows boxes use 139, others 445 (Defaults to smbclient default)
264 If thresholds are followed by either a k, M, or G then check to see if that
265 much disk space is available (kilobytes, Megabytes, Gigabytes)
267 Warning percentage should be less than critical
268 Warning (remaining) disk space should be greater than critical.
270 ";
271 support();
272 }