diff options
| -rwxr-xr-x | contrib/check_ms_spooler.pl | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/contrib/check_ms_spooler.pl b/contrib/check_ms_spooler.pl new file mode 100755 index 00000000..cf2464af --- /dev/null +++ b/contrib/check_ms_spooler.pl | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | #!/usr/bin/perl -w | ||
| 2 | |||
| 3 | # $Id$ | ||
| 4 | |||
| 5 | # $Log$ | ||
| 6 | # Revision 1.1 2002/07/16 00:04:42 stanleyhopcroft | ||
| 7 | # Primitive and in need of refinement test of MS spooler (with smbclient) | ||
| 8 | # | ||
| 9 | # Revision 2.5 2002-02-13 07:36:08+11 anwsmh | ||
| 10 | # Correct 'apostrophe' disaster. | ||
| 11 | # Apostrophes in plugin output cause Netsaint notification commands | ||
| 12 | # ( sh echo 'yada $PLUGINOUTPUT$ ..') to fail, usually mysteriously | ||
| 13 | # eg notify OK works but notify CRITICAL does not. | ||
| 14 | # Replace '$var' in print "output" with \"$var\". | ||
| 15 | # | ||
| 16 | # Revision 2.4 2001-11-21 21:36:05+11 anwsmh | ||
| 17 | # Minor corrections | ||
| 18 | # . replace 'die' by print .. exit $ERRORS{CRITICAL} | ||
| 19 | # . change concluding message to list the queues (sorted) if there are no enqueued docs. | ||
| 20 | # | ||
| 21 | # Revision 2.3 2001-11-20 11:00:58+11 anwsmh | ||
| 22 | # Major corrections. | ||
| 23 | # 1. to sub AUTOLOAD: coderef parms must be @_ (ie the parm when the new sub is called) | ||
| 24 | # 2. to processing of queue report (no inspection of $last_line; entire $queue_report is | ||
| 25 | # checked for errors) | ||
| 26 | # 3. cosmetic and debug changes in many places. | ||
| 27 | # | ||
| 28 | # Revision 2.2 2001-11-17 23:30:34+11 anwsmh | ||
| 29 | # After adapting two different queue reports resulting from | ||
| 30 | # different name resolution methods. | ||
| 31 | # | ||
| 32 | # Revision 2.1 2001-11-17 13:21:54+11 anwsmh | ||
| 33 | # Adapt to Netsaint ('use utils, Getopt::Long, and standard switch processing). | ||
| 34 | # Fix many peculiarities. | ||
| 35 | # | ||
| 36 | |||
| 37 | |||
| 38 | use strict ; | ||
| 39 | |||
| 40 | use Getopt::Long ; | ||
| 41 | use utils ; | ||
| 42 | |||
| 43 | use vars qw($opt_H $opt_s $opt_W $opt_u $opt_p $opt_w $opt_c $debug); | ||
| 44 | use vars '$AUTOLOAD' ; | ||
| 45 | use utils qw($TIMEOUT %ERRORS &print_revision &support &usage); | ||
| 46 | |||
| 47 | my $PROGNAME = 'check_ms_spooler' ; | ||
| 48 | |||
| 49 | sub print_help (); | ||
| 50 | sub print_usage (); | ||
| 51 | sub help (); | ||
| 52 | sub version (); | ||
| 53 | |||
| 54 | delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; | ||
| 55 | |||
| 56 | use constant SMBCLIENT_PATH => '/usr/local/samba/bin/smbclient' ; | ||
| 57 | use constant MAX_QUEUES_TO_CHECK => 20 ; # So that the check doesn't take longer than $TIMEOUT | ||
| 58 | |||
| 59 | use constant SMBCLIENT_SVC => sub { return `${\SMBCLIENT_PATH} -L //$_[0] -U $_[1]%$_[2]` } ; | ||
| 60 | use constant SMBCLIENT_QUEUE => sub { return `${\SMBCLIENT_PATH} //$_[0]/$_[1] -U $_[2]%$_[3] -c 'queue; quit' 2>/dev/null` } ; | ||
| 61 | |||
| 62 | # The queue results depend on the name resolution method. | ||
| 63 | |||
| 64 | # Forcing 'wins' or 'bcat' name resolution makes the queue results the | ||
| 65 | # same for all spoolers (those that are resolved with WINS have an extra line | ||
| 66 | # 'Got a positive name query response from <ip address of WINS> ..) | ||
| 67 | # but would fail if there is no WINS and when miscreant spoolers | ||
| 68 | # don't respond to broadcasts. | ||
| 69 | |||
| 70 | use constant MIN => sub { my $min = $_[0] ; foreach (@_) { $min = $_ if $_ <= $min; } return $min ; } ; | ||
| 71 | |||
| 72 | $SIG{"ALRM"} = sub { die "Alarm clock restart" } ; | ||
| 73 | |||
| 74 | Getopt::Long::Configure('bundling', 'no_ignore_case'); | ||
| 75 | GetOptions | ||
| 76 | ("V|version" => \&version, | ||
| 77 | "h|help" => \&help, | ||
| 78 | "d|debug" => \$debug, | ||
| 79 | "p|password=s" => \$opt_p, | ||
| 80 | "u|username=s" => \$opt_u, | ||
| 81 | "H|hostname=s" => \$opt_H); | ||
| 82 | |||
| 83 | |||
| 84 | |||
| 85 | ($opt_H) || usage("MS Spooler name not specified\n"); | ||
| 86 | my $spooler = $1 if $opt_H =~ m#(\w+)# ; # MS host names allow __any__ characters (more than \w) | ||
| 87 | ($spooler) || usage("Invalid MS spooler name: $opt_H\n"); | ||
| 88 | |||
| 89 | ($opt_u) || ($opt_u = 'guest'); | ||
| 90 | my $user = $1 if $opt_u =~ m#(\w+)# ; | ||
| 91 | ($user) || usage("Invalid user: $opt_u\n"); | ||
| 92 | |||
| 93 | ($opt_p) || ($opt_p = 'guest'); | ||
| 94 | my $pass = $1 if ($opt_p =~ /(.*)/); | ||
| 95 | ($pass) || usage("Invalid password: $opt_p\n"); | ||
| 96 | |||
| 97 | my ($printer, $queue, @queues, $ms_spooler_status, @results, %junk) ; | ||
| 98 | my (@fault_messages, @queue_contents, @services, @prandom_queue_indices) ; | ||
| 99 | my ($queue_contents, $number_of_queues, $state, $queue_report) ; | ||
| 100 | |||
| 101 | $state = "getting service list (${\SMBCLIENT_PATH} -L $spooler -U $user%$pass) from spooler\n" ; | ||
| 102 | |||
| 103 | eval { | ||
| 104 | alarm($TIMEOUT) ; | ||
| 105 | @services = SMBCLIENT_SVC->( $spooler, $user, $pass ) ; | ||
| 106 | } ; | ||
| 107 | alarm(0) ; | ||
| 108 | |||
| 109 | if ($@ and $@ !~ /Alarm clock restart/) { | ||
| 110 | print "Failed. $PROGNAME failed $state. Got \"$@\"\n" ; | ||
| 111 | exit $ERRORS{"CRITICAL"} ; | ||
| 112 | } | ||
| 113 | |||
| 114 | if ($@ and $@ =~ /Alarm clock restart/) { | ||
| 115 | print "Failed. $PROGNAME timed out $state. Got \"@services\"\n" ; | ||
| 116 | exit $ERRORS{"CRITICAL"} ; | ||
| 117 | } | ||
| 118 | |||
| 119 | # tsitc> /usr/local/samba/bin/smbclient //ipaprint1/tt03 -U blah%blah -P -c 'queue; quit' | ||
| 120 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 121 | # Connection to ipaprint1 failed | ||
| 122 | |||
| 123 | # tsitc> /usr/local/samba/bin/smbclient -L sna_spl1 -U blah%blah | & more | ||
| 124 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 125 | # Got a positive name query response from 10.0.100.29 ( 10.0.6.20 ) | ||
| 126 | # session setup failed: ERRDOS - ERRnoaccess (Access denied.) | ||
| 127 | |||
| 128 | if ( grep /Connection to $spooler failed|ERR/, @services ) { | ||
| 129 | print "Failed. $PROGNAME failed $state. Got \"@services\"\n" ; | ||
| 130 | # print "Failed. Request for services list to $spooler failed. Got \"@services\"\n" ; | ||
| 131 | exit $ERRORS{"CRITICAL"} ; | ||
| 132 | } | ||
| 133 | |||
| 134 | # tsitc# /usr/local/samba/bin/smbclient -L ipaprint -U blah%blah | ||
| 135 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 136 | # Domain=[IPAUSTRALIA] OS=[Windows NT 4.0] Server=[NT LAN Manager 4.0] | ||
| 137 | # | ||
| 138 | # Sharename Type Comment | ||
| 139 | # --------- ---- ------- | ||
| 140 | # TH02 Printer TH02 | ||
| 141 | # ADMIN$ Disk Remote Admin | ||
| 142 | # IPC$ IPC Remote IPC | ||
| 143 | # S431 Printer S431 | ||
| 144 | # S402 Printer S402 | ||
| 145 | # S401 Printer S401 | ||
| 146 | # C$ Disk Default share | ||
| 147 | # BW01 Printer BW01 | ||
| 148 | # BW02 Printer BW02 | ||
| 149 | # TL11 Printer TL11 | ||
| 150 | # TL07 Printer TL07 | ||
| 151 | # S225 Printer Discovery South - 2nd Floor - HP CLJ4500 | ||
| 152 | # S224 Printer S224 | ||
| 153 | # S223 Printer Discovery South 2nd Floor Trademarks Training | ||
| 154 | # S222 Printer S222 | ||
| 155 | # S203 Printer S203 | ||
| 156 | # S202 Printer S202 | ||
| 157 | |||
| 158 | my @printers = map { my @junk = split; $junk[0] } | ||
| 159 | grep { my @junk = split; defined $junk[1] and $junk[1] eq 'Printer' } @services ; | ||
| 160 | # don't check IPC$, ADMIN$ etc. | ||
| 161 | |||
| 162 | $ms_spooler_status = 0 ; | ||
| 163 | $number_of_queues = MIN->(MAX_QUEUES_TO_CHECK, (scalar(@services) >> 3) + 1) ; | ||
| 164 | |||
| 165 | $state = "checking queues on $spooler" ; | ||
| 166 | |||
| 167 | eval { | ||
| 168 | # foreach queues to check | ||
| 169 | # generate a pseudo-random int in 0 .. $#printers | ||
| 170 | # drop it if the index has already been generated ; | ||
| 171 | |||
| 172 | %junk = () ; | ||
| 173 | @prandom_queue_indices = grep { ! $junk{$_}++ } | ||
| 174 | map { int( rand($#printers) ) } ( 1 .. $number_of_queues ) ; | ||
| 175 | |||
| 176 | @queues = @printers[@prandom_queue_indices] ; | ||
| 177 | |||
| 178 | # @queues = @printers[ map { int( rand($#printers) ) } ( 1 .. $number_of_queues ) ] ; | ||
| 179 | |||
| 180 | alarm($TIMEOUT) ; | ||
| 181 | |||
| 182 | @queue_contents = @fault_messages = () ; | ||
| 183 | |||
| 184 | foreach $printer (sort @queues) { | ||
| 185 | |||
| 186 | # Expect 3 lines from a queue report. | ||
| 187 | # If queue is empty, last line is null otherwise | ||
| 188 | # it will contain a queue report or an SMB error | ||
| 189 | |||
| 190 | # Empty Queue. | ||
| 191 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 192 | # Domain=[IPAUSTRALIA] OS=[Windows NT 4.0] Server=[NT LAN Manager 4.0] | ||
| 193 | |||
| 194 | # Queue command from a spooler with a DNS name. | ||
| 195 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 196 | # Domain=[IPAUSTRALIA] OS=[Windows NT 4.0] Server=[NT LAN Manager 4.0] | ||
| 197 | # 65 16307 Microsoft Word - Servicesweoffer2.doc | ||
| 198 | # 68 10410 Microsoft Word - Servicesweoffer.doc | ||
| 199 | # 143 24997 Microsoft Word - Miss Samantha Anne Craig.doc | ||
| 200 | # 182 15635 Microsoft Word - services we provide.doc | ||
| 201 | |||
| 202 | # Error. | ||
| 203 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 204 | # Domain=[IPAUSTRALIA] OS=[Windows NT 4.0] Server=[NT LAN Manager 4.0] | ||
| 205 | # tree connect failed: ERRDOS - ERRnosuchshare (You specified an invalid share name) | ||
| 206 | |||
| 207 | # Can't connect error. | ||
| 208 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 209 | # Connection to sna_spl2 failed | ||
| 210 | |||
| 211 | |||
| 212 | # Empty Queue from a spooler with no DNS name, NetBIOS name resolved by WINS. | ||
| 213 | # Added interface ip=10.0.100.252 bcast=10.255.255.255 nmask=255.0.0.0 | ||
| 214 | # Got a positive name query response from 10.0.100.29 ( 10.0.6.20 ) | ||
| 215 | # Domain=[SNA_PRINT] OS=[Windows NT 4.0] Server=[NT LAN Manager 4.0] | ||
| 216 | |||
| 217 | # There are 3 lines of output from smbclient for those spoolers whose names are | ||
| 218 | # resolved by WINS (because those names are NetBIOS and therefore not in DNS); | ||
| 219 | # 4 lines for errors or enqueued jobs | ||
| 220 | |||
| 221 | print STDERR "${\SMBCLIENT_PATH} //$spooler/$printer -U $user%$pass -c 'queue; quit' ==>\n" if $debug ; | ||
| 222 | |||
| 223 | @results = SMBCLIENT_QUEUE->( $spooler, $printer, $user, $pass ) ; | ||
| 224 | |||
| 225 | print STDERR "\"@results\"\n" if $debug ; | ||
| 226 | |||
| 227 | # set $ms_spooler_status somehow | ||
| 228 | |||
| 229 | chomp( @results ) ; | ||
| 230 | $queue_report = queue_report->(@results) ; | ||
| 231 | print STDERR '$queue_report for $printer ', "$printer: \"$queue_report\"\n\n" if $debug ; | ||
| 232 | |||
| 233 | if ( defined $queue_report and ($queue_report !~ /ERR/ && $queue_report !~ /failed/) ) { | ||
| 234 | $ms_spooler_status = 1 ; | ||
| 235 | push @queue_contents, "$printer: $queue_report" if $queue_report ; | ||
| 236 | } else { | ||
| 237 | push @fault_messages, "$printer: $queue_report" ; | ||
| 238 | } | ||
| 239 | } | ||
| 240 | alarm(0) ; | ||
| 241 | } ; | ||
| 242 | |||
| 243 | if ($@ and $@ !~ /Alarm clock restart/) { | ||
| 244 | print "Failed. $PROGNAME failed at $state. Got \"$@\"\n" ; | ||
| 245 | exit $ERRORS{"CRITCAL"} ; | ||
| 246 | } | ||
| 247 | |||
| 248 | if ($@ and $@ =~ /Alarm clock restart/) { | ||
| 249 | my $i ; | ||
| 250 | foreach (@queues) { $i++ ; last if $_ eq $printer } | ||
| 251 | print "Failed. Timed out connecting to $printer ($i of $number_of_queues) on //$spooler after $TIMEOUT secs. Got \"@fault_messages\"\n" ; | ||
| 252 | exit $ERRORS{"CRITICAL"} ; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (! $ms_spooler_status) { | ||
| 256 | print "Failed. Couldn't connect to @queues on //$spooler as user $user. Got \"@fault_messages\"\n" ; | ||
| 257 | exit $ERRORS{"CRITICAL"} ; | ||
| 258 | } | ||
| 259 | |||
| 260 | $queue_contents = ( @queue_contents != 0 ? join(" ", (@queue_contents == 1 ? "Queue" : "Queues"), @queue_contents) : | ||
| 261 | "All Queues empty" ) ; | ||
| 262 | |||
| 263 | print "Ok. Connected to ", $queue_contents =~ /empty$/ ? "@{[sort @queues]}" : scalar @queues, " queues on //$spooler. $queue_contents\n" ; | ||
| 264 | exit $ERRORS{"OK"} ; | ||
| 265 | |||
| 266 | sub print_usage () { | ||
| 267 | print "Usage: $PROGNAME -H <spooler> -u <user> -p <password>\n"; | ||
| 268 | } | ||
| 269 | |||
| 270 | sub print_help () { | ||
| 271 | print_revision($PROGNAME,'$Revision$ '); | ||
| 272 | print "Copyright (c) 2001 Karl DeBisschop/S Hopcroft | ||
| 273 | |||
| 274 | Perl Check MS Spooler plugin for NetSaint. Display a subset of the queues on an SMB (Samba or MS) print spooler. | ||
| 275 | |||
| 276 | "; | ||
| 277 | print_usage(); | ||
| 278 | print ' | ||
| 279 | -H, --hostname=STRING | ||
| 280 | NetBIOS name of the SMB Print spooler (Either Samba or MS spooler) | ||
| 281 | -u, --user=STRING | ||
| 282 | Username to log in to server. (Default: "guest") | ||
| 283 | -p, --password=STRING | ||
| 284 | Password to log in to server. (Default: "guest") | ||
| 285 | -d, --debug | ||
| 286 | Debugging output. | ||
| 287 | -h, --help | ||
| 288 | This stuff. | ||
| 289 | |||
| 290 | '; | ||
| 291 | support(); | ||
| 292 | } | ||
| 293 | |||
| 294 | sub version () { | ||
| 295 | print_revision($PROGNAME,'$Revision$ '); | ||
| 296 | exit $ERRORS{'OK'}; | ||
| 297 | } | ||
| 298 | |||
| 299 | sub help () { | ||
| 300 | print_help(); | ||
| 301 | exit $ERRORS{'OK'}; | ||
| 302 | } | ||
| 303 | |||
| 304 | sub AUTOLOAD { | ||
| 305 | |||
| 306 | my @queue_rep = @_ ; | ||
| 307 | |||
| 308 | # 'Object Oriented Perl', D Conway, p 95 | ||
| 309 | |||
| 310 | no strict 'refs' ; | ||
| 311 | |||
| 312 | if ( $AUTOLOAD =~ /.*::queue_report/ ) { | ||
| 313 | |||
| 314 | if ( grep /Got a positive name query response from/, @queue_rep ){ | ||
| 315 | *{$AUTOLOAD} = sub { return join ' ', splice(@_, 3) } ; | ||
| 316 | return join '', splice(@queue_rep, 3) ; | ||
| 317 | } else { | ||
| 318 | *{$AUTOLOAD} = sub { return join ' ',splice(@_, 2) } ; | ||
| 319 | return join '', splice(@queue_rep, 2) ; | ||
| 320 | } | ||
| 321 | } else { | ||
| 322 | die "No such subroutine: $AUTOLOAD" ; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | |||
