/[nagios-plugins-perl]/trunk/plugins/check_httpd_status.pl
ViewVC logotype

Contents of /trunk/plugins/check_httpd_status.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 204 - (show annotations) (download)
Fri Oct 5 14:59:46 2018 UTC (2 years, 1 month ago) by racvision
File MIME type: text/plain
File size: 11285 byte(s)
Fusion des modifs sur supervision01/02 et racvision3. Pas fini.
1 #!/usr/bin/perl -w
2 ####################### check_httpd_status.pl #######################
3 # Version : 1.3
4 # Date : 06 Aug 2010
5 #
6 # V1.3 Rewrite using Nagios::Plugin, rename check_httpd_status.pl (St├ęphane Urbanovski)
7 # V1.2 Updated perf data to be PNP compliant, added proxy option (Gerhard Lausser)
8 # V1.1 Works with lighttpd server-status as well, added accesses perfdata
9 # V1.0 Inital Release
10 #
11 #
12 # Authors : Dennis D. Spreen (dennis at spreendigital.de)
13 # Based on check_apachestatus.pl v1.4 by
14 # De Bodt Lieven (Lieven dot DeBodt at gmail.com)
15 # Updated by
16 # Karsten Behrens (karsten at behrens dot in)
17 # Geoff McQueen (geoff dot mcqueen at hiivesystems dot com )
18 # Dave Steinberg (dave at redterror dot net)
19 # Updated by
20 # Gerhard Lausser (gerhard dot lausser at consol dot de)
21 # Licence : GPL - http://www.fsf.org/licenses/gpl.txt
22 #############################################################
23 #
24 #
25
26 use strict;
27 use warnings;
28 #use Data::Dumper;
29
30 use File::Basename; # get basename()
31
32 use POSIX qw(setlocale);
33 use Locale::gettext;
34
35 use Nagios::Plugin ;
36
37 use LWP::UserAgent;
38 use HTTP::Status; # get status_message()
39 use Time::HiRes qw(gettimeofday tv_interval);
40 use Digest::MD5 qw(md5 md5_hex);
41
42
43 # Globals
44
45 my $VERSION = '1.3';
46 my $TIMEOUT = 10;
47 my $PROGNAME = basename($0);
48 # my $PROGNAME = 'check_httpd_status.pl';
49
50 # Retention files path (save previous values) :
51 # FIXME: Make this configurable
52 my $TempPath = '/tmp/';
53
54 # Check freshness og previous values
55 my $MaxUptimeDif = 60*30; # Maximum uptime difference (seconds), default 30 minutes
56
57
58 # i18n :
59 setlocale(LC_MESSAGES, '');
60 textdomain('nagios-plugins-perl');
61
62 # Translate Apache / lighthttpd scoreboard status
63 my %TranslationTable = (
64 'APACHE' => {
65 '.' => 'OpenSLot',
66 '_' => 'Waiting',
67 'I' => 'Idle',
68 'S' => 'Starting',
69 'R' => 'Reading',
70 'W' => 'Sending',
71 'K' => 'Keepalive',
72 'D' => 'DNS',
73 'C' => 'Closing',
74 'L' => 'Logging',
75 'G' => 'Finishing',
76 },
77 'LIGHTTPD' => {
78 '.' => 'Connect',
79 'C' => 'Close',
80 'E' => 'HardError',
81 'r' => 'Read',
82 'R' => 'ReadPost',
83 'W' => 'Write',
84 'h' => 'HandleRequest',
85 'q' => 'RequestStart',
86 'Q' => 'ReqestEnd',
87 's' => 'ResponseStart',
88 'S' => 'ResponseEnd',
89 },
90 );
91
92
93 my $np = Nagios::Plugin->new(
94 version => $VERSION,
95 blurb => _gt('Apache / Lighthttpd server status monitor for Nagios'),
96 usage => "Usage: %s [ -H <host> [-p <port>] [-t <timeout>] [-w <warn_level> -c <crit_level>] [-V] [-u <url>] [-U user -P pass -r realm]",
97 extra => &showExtra(),
98 timeout => $TIMEOUT+1
99 );
100
101 $np->add_arg (
102 spec => 'hostname|H=s',
103 help => _gt('Name or IP address of host to check'),
104 required => 1,
105 );
106
107 $np->add_arg (
108 spec => 'port|p=i',
109 help => _gt('Http port'),
110 );
111 $np->add_arg (
112 spec => 'url|u=s',
113 help => _gt('Specific URL to use, instead of the default http://<hostname>/server-status?auto'),
114 default => '/server-status?auto',
115 );
116
117 $np->add_arg (
118 spec => 'user|U=s',
119 help => _gt('Username for basic auth'),
120 );
121 $np->add_arg (
122 spec => 'pass|P=s',
123 help => _gt('Password for basic auth'),
124 );
125 $np->add_arg (
126 spec => 'realm|r=s',
127 help => _gt('Realm for basic auth'),
128 );
129 $np->add_arg (
130 spec => 'proxy|X=s',
131 help => _gt('Proxy-URL for http and https (mandatory)'),
132 );
133
134 $np->add_arg (
135 spec => 'warn|w=s',
136 help => _gt('Number of available slots that will cause a warning (Range format).'),
137 );
138 $np->add_arg (
139 spec => 'crit|c=s',
140 help => _gt('Number of available slots that will cause an error (Range format).'),
141 );
142
143
144 $np->getopts;
145
146 my $o_host = $np->opts->get('hostname');
147 my $o_port = $np->opts->get('port');
148 my $o_url = $np->opts->get('url');
149 my $o_user = $np->opts->get('user');
150 my $o_pass = $np->opts->get('pass');
151 my $o_realm = $np->opts->get('realm');
152 my $o_proxy = $np->opts->get('proxy');
153 my $o_warn_level = $np->opts->get('warn');
154 my $o_crit_level = $np->opts->get('crit');
155
156 # if (((defined($o_warn_level) && !defined($o_crit_level)) ||
157 # (!defined($o_warn_level) && defined($o_crit_level))) ||
158 # ((defined($o_warn_level) && defined($o_crit_level)) && (($o_warn_level != -1) && ($o_warn_level <= $o_crit_level)))
159 # ) {
160 # $np->nagios_exit(UNKNOWN, _gt("Check warn and crit!") );
161 # }
162
163 my $o_proto = 'http';
164 my $url = undef;
165 my $httpserver = 'APACHE'; #assume it is apache by default
166
167 if (($o_url =~ m/^http(s?)\:\/\//i) ){
168 $url = $o_url;
169 if ($1 eq 's') {
170 $o_proto = 'https';
171 }
172 } else {
173 $url = $o_proto.'://' . $o_host;
174 if ( defined($o_port)) {
175 $url .= ':' . $o_port;
176 }
177 if ( $o_url !~ /^\// ) {
178 $url .= '/';
179 }
180 $url .= $o_url;
181 }
182
183 if ( $url !~ /\?auto$/ ) {
184 $url .= '/server-status?auto';
185 }
186
187 my $ua = LWP::UserAgent->new( protocols_allowed => ['http', 'https'], timeout => $TIMEOUT);
188 $ua->agent($PROGNAME.'-'.$VERSION);
189
190
191 logD("Web URL : $url");
192
193 my $req = HTTP::Request->new( GET => $url );
194 if ( defined($o_user) ) {
195 $req->authorization_basic($o_user, $o_pass);
196 }
197
198 if ( defined($o_proxy) ) {
199 if ($o_proto eq 'https') {
200 if ($o_proxy =~ /^http:\/\/(.*?)\/?$/) {
201 $o_proxy = $1;
202 }
203 $ENV{HTTPS_PROXY} = $o_proxy;
204 } else {
205 $ua->proxy(['http'], $o_proxy);
206 }
207 }
208
209 my $timing0 = [gettimeofday];
210 my $response = $ua->request($req);
211 my $timeelapsed = tv_interval($timing0, [gettimeofday]);
212
213
214 if ( $response->is_error() ) {
215 my $err = $response->code." ".status_message($response->code)." (".$response->message.")";
216 my $status = CRITICAL;
217 $np->add_message(CRITICAL, );
218
219 if (defined($o_warn_level) || defined($o_crit_level)) {
220 $status = UNKNOWN;
221 }
222 $np->nagios_exit($status, _gt("HTTP error: ").$err );
223
224 } elsif ( ! $response->is_success() ) {
225 my $err = $response->code." ".status_message($response->code)." (".$response->message.")";
226 $np->add_message(CRITICAL, _gt("Internal error: ").$err );
227 }
228
229
230
231 my $webcontent = $response->content;
232
233 logD("Web content :\n----------------------------\n".$webcontent."\n----------------------------");
234
235 my $patternFound = 0;
236
237 my $Uptime = 0;
238 # if ( $webcontent =~ m/Uptime: (.*?)\n/) {
239 # $Uptime = $1;
240 # $patternFound++;
241 # }
242 ### FIXME XH 20171204 catch ServerUptimeSeconds, not [Server]Uptime. Change in server-status between 2.2 & 2.4
243 if ( $webcontent =~ m/\b(ServerUptimeSeconds|Uptime): (\d+)\n/) {
244 $Uptime = $2;
245 $patternFound++;
246 }
247
248 my $TotalAccesses = 0;
249 if ( $webcontent =~ m/Total Accesses: (.*?)\n/) {
250 $TotalAccesses = $1;
251 $patternFound++;
252 } else {
253 $np->add_message(WARNING, _gt('"Total Accesses" not set ! (need extented status ?)') );
254 }
255
256 my $TotalKbytes = 0;
257 if ( $webcontent =~ m/Total kBytes: (.*?)\n/) {
258 $TotalKbytes = $1;
259 $patternFound++;
260 }
261
262 my $ScoreBoard = '';
263 if ( $webcontent =~ m/Scoreboard: (.*?)\n/) {
264 $ScoreBoard = $1;
265 $patternFound++;
266 } else {
267 $np->add_message(WARNING, _gt("Scoreboard not found in reponse !") );
268 }
269
270 my $BusyWorkers = 0;
271 if ( $webcontent =~ m/(BusyWorkers|BusyServers): (.*?)\n/) {
272 $BusyWorkers = $2;
273 $patternFound++;
274 if ($1 eq 'BusyServers') {
275 $httpserver = 'LIGHTTPD';
276 }
277 }
278
279 my $IdleWorkers = 0;
280 if ( $webcontent =~ m/(IdleWorkers|IdleServers): (.*?)\n/) {
281 $IdleWorkers = $2;
282 $patternFound++;
283 }
284
285 if ( $patternFound <= 1) {
286 $np->nagios_exit(CRITICAL, _gt("Server-status informations not found !") );
287 }
288
289
290 my $TempFile = $TempPath.$o_host.'_check_httpd_status'.md5_hex($url);
291
292 my $LastUptime = 0;
293 my $LastTotalAccesses = 0;
294 my $LastTotalKbytes = 0;
295
296 if ((-e $TempFile) && (-r $TempFile) && (-w $TempFile)) {
297 if ( !open (RETENTION_FILE, '<',$TempFile) ) {
298 $np->nagios_exit(CRITICAL, sprintf(_gt('Error while trying to read %s !'),$TempFile) );
299 }
300 $LastUptime = <RETENTION_FILE>;
301 $LastTotalAccesses = <RETENTION_FILE>;
302 $LastTotalKbytes = <RETENTION_FILE>;
303 close (RETENTION_FILE);
304 chomp($LastUptime);
305 chomp($LastTotalAccesses);
306 chomp($LastTotalKbytes);
307 logD("LastUptime=$LastUptime LastTotalAccesses=$LastTotalAccesses LastTotalKbytes=$LastTotalKbytes (from $TempFile)");
308
309 } else {
310 logD("Retention file '$TempFile' not found");
311 }
312
313 if ( !open (RETENTION_FILE, '>',$TempFile) ) {
314 $np->nagios_exit(CRITICAL, sprintf(_gt('Error while trying to write to %s !'),$TempFile) );
315 }
316 print RETENTION_FILE "$Uptime\n";
317 print RETENTION_FILE "$TotalAccesses\n";
318 print RETENTION_FILE "$TotalKbytes\n";
319 close (RETENTION_FILE);
320
321 my $ReqPerSec = 0;
322 my $BytesPerReq = 0;
323 my $BytesPerSec = 0;
324
325 my $DiffTime = $Uptime-$LastUptime;
326
327 if ( ($DiffTime > 0) && ($DiffTime < $MaxUptimeDif) && ($TotalAccesses >= $LastTotalAccesses) && ($TotalKbytes >= $LastTotalKbytes) ) {
328
329 $ReqPerSec = ($TotalAccesses-$LastTotalAccesses)/$DiffTime;
330 $np->add_perfdata(
331 'label' => 'ReqPerSec',
332 'value' => sprintf('%.3f',$ReqPerSec),
333 'uom' => 'req/s',
334 );
335
336 $BytesPerSec = (($TotalKbytes-$LastTotalKbytes)*1024)/$DiffTime;
337 $np->add_perfdata(
338 'label' => 'BytesPerSec',
339 'value' => sprintf('%.2f',$BytesPerSec),
340 'uom' => 'B/s',
341 );
342
343 my $Accesses = ($TotalAccesses-$LastTotalAccesses);
344
345 if ( $Accesses > 0 ) {
346 $BytesPerReq = (($TotalKbytes-$LastTotalKbytes)*1024)/$Accesses;
347 $np->add_perfdata(
348 'label' => 'BytesPerReq',
349 'value' => sprintf('%.2f',$BytesPerReq),
350 'uom' => 'B/req',
351 );
352 }
353 }
354
355 my $CountOpenSlots = ($ScoreBoard =~ tr/\.//);
356 my $TotalSlots = $CountOpenSlots+$IdleWorkers+$BusyWorkers;
357 my $InfoData = '';
358
359 my %WorkerStates = ();
360
361 map( $WorkerStates{$_}++ , split(//,$ScoreBoard) );
362
363
364 foreach my $slotState ( sort(keys(%{$TranslationTable{$httpserver}})) ) {
365 my $val = 0 ;
366 if ( defined($WorkerStates{$slotState}) ) {
367 $val = $WorkerStates{$slotState};
368 }
369
370 $np->add_perfdata(
371 'label' => $TranslationTable{$httpserver}{$slotState},
372 'value' => $val,
373 );
374 }
375
376
377 if ( $httpserver eq 'APACHE' ) {
378 $InfoData = sprintf ("%.3f s - %d/%d Busy/Idle, %d/%d Open/Total, %.1f requests/s, %.1f B/s, %d B/request",
379 $timeelapsed, $BusyWorkers, $IdleWorkers, $CountOpenSlots, $TotalSlots, $ReqPerSec, $BytesPerSec, $BytesPerReq);
380
381 } else {
382 $InfoData = sprintf ("%.3f sec. response time, Busy/Idle %d/%d, slots %d, ReqPerSec %.1f, BytesPerReq %d, BytesPerSec %d",
383 $timeelapsed, $BusyWorkers, $IdleWorkers, $TotalSlots, $ReqPerSec, $BytesPerReq, $BytesPerSec);
384
385 }
386
387 $np->add_message(OK, $InfoData);
388
389
390 my $fw = $CountOpenSlots + $IdleWorkers;
391
392 logD("FreeWorker = ".$fw);
393
394 my $tmp_status = $np->check_threshold(
395 check => $fw,
396 warning => $o_warn_level,
397 critical => $o_crit_level,
398 );
399
400 $np->add_perfdata(
401 'label' => 'FreeWorker',
402 'value' => $fw,
403 'min' => 0,
404 'threshold' => $np->threshold()
405 );
406
407 if ( $tmp_status ) {
408 $np->add_message($tmp_status, sprintf(_gt(" Not enough free worker (%d) !"),$fw) );
409 }
410
411
412
413 my ($status, $message) = $np->check_messages('join' => ' ');
414 $np->nagios_exit($status, $message );
415
416
417 sub logD {
418 print STDERR 'DEBUG: '.$_[0]."\n" if ($np->opts->verbose);
419 }
420 sub logW {
421 print STDERR 'WARNING: '.$_[0]."\n" if ($np->opts->verbose);
422 }
423 # Gettext wrapper
424 sub _gt {
425 return gettext($_[0]);
426 }
427 sub showExtra {
428 return <<EOT;
429 (c)2009 Dennis D. Spreen
430 (c)2010 St├ęphane Urbanovski
431
432 Note :
433
434 This plugin check Apache or Lighthttpd server-status page (using mod_status). It require the ?auto option.
435
436 Warning and critical values follow Nagios::Plugins::Threshold format. See http://nagiosplug.sourceforge.net/developer-guidelines.html
437
438 Example (note the trailing colon):
439
440 check_httpd_status -H www.server.org -w 100: -c 10:
441 Warn if less than 100 workers are available
442 Crit if less than 10 workers are available
443 EOT
444 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.8