check_apache.pl 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #!/usr/bin/perl
  2. #
  3. # (c)2001 Sebastian Hetze, Linux Information Systems AG
  4. # send bug reports to <S.Hetze@Linux-AG.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License
  8. # as published by the Free Software Foundation; either version 2
  9. # of the License, or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty
  13. # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # you should have received a copy of the GNU General Public License
  17. # along with this program (or with Nagios); if not, write to the
  18. # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. # Boston, MA 02111-1307, USA
  20. #
  21. #
  22. # Check apache status information provided by mod_status to find
  23. # out about the load (number of servers working) and the
  24. # performance (average response time for recent requests).
  25. #
  26. # Usage:
  27. # check_apache -H <host> [-lhV] [-w <warn>] [-c <crit>] [-u <url>]
  28. #
  29. # check_apache <host> <warn> <crit> <url> (if you cannot avoid it)
  30. #
  31. use LWP::UserAgent;
  32. use URI::URL;
  33. use Getopt::Long;
  34. Getopt::Long::Configure('bundling');
  35. $version=0.01;
  36. my %ERRORS = ('UNKNOWN' , '-1',
  37. 'OK' , '0',
  38. 'WARNING', '1',
  39. 'CRITICAL', '2');
  40. #
  41. # some default values
  42. #
  43. $perf_w=500;
  44. $perf_c=1000;
  45. $load_w=20;
  46. $load_c=30;
  47. $TIMEOUT=15;
  48. #
  49. # get command line options the regular way
  50. #
  51. GetOptions
  52. ("V" => \$opt_V, "version" => \$opt_V,
  53. "h" => \$opt_h, "help" => \$opt_h,
  54. "l" => \$opt_l, "load" => \$opt_l,
  55. "v" => \$verbose, "verbose" => \$verbose,
  56. "w=s" => \$opt_w, "warning=s" => \$opt_w,
  57. "c=s" => \$opt_c, "critical=s" => \$opt_c,
  58. "H=s" => \$opt_H, "hostname=s" => \$opt_H,
  59. "u=s" => \$opt_u, "url=s" => \$opt_u);
  60. #
  61. # handle the verbose stuff first
  62. #
  63. if ($opt_V) {
  64. print "\n";
  65. print "check_apache nagios plugin version $version\n";
  66. print "\n";
  67. print "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n";
  68. print "copies of the plugins under the terms of the GNU General Public License.\n";
  69. print "For more information about these matters, see the file named COPYING.\n";
  70. print "\n";
  71. print "Copyright (c) 2001 Sebastian Hetze Linux Information Systems AG\n";
  72. print "\n";
  73. print "\n";
  74. exit $ERRORS{'UNKNOWN'};
  75. }
  76. if ($opt_h) {
  77. print_help();
  78. exit $ERRORS{'UNKNOWN'};
  79. }
  80. #
  81. # now get options the weired way and set the defaults
  82. # if nothing else is provided
  83. #
  84. $opt_H = shift unless ($opt_H);
  85. print_usage() unless ($opt_H);
  86. if($opt_l) {
  87. $autostring="?auto";
  88. ($opt_w) || ($opt_w = shift) || ($opt_w = $load_w);
  89. $warn = $1 if ($opt_w =~ /([0-9]+)/);
  90. ($opt_c) || ($opt_c = shift) || ($opt_c = $load_c);
  91. $alert = $1 if ($opt_c =~ /([0-9]+)/);
  92. } else {
  93. $autostring="";
  94. ($opt_w) || ($opt_w = shift) || ($opt_w = $perf_w);
  95. $warn = $1 if ($opt_w =~ /([0-9]+)/);
  96. ($opt_c) || ($opt_c = shift) || ($opt_c = $perf_c);
  97. $alert = $1 if ($opt_c =~ /([0-9]+)/);
  98. }
  99. ($opt_u) || ($opt_u = shift) || ($opt_u = "/server-status");
  100. #
  101. # dont let us wait forever...
  102. #
  103. $SIG{'ALRM'} = sub {
  104. print ("ERROR: No response from HTTP server (alarm)\n");
  105. exit $ERRORS{"UNKNOWN"};
  106. };
  107. alarm($TIMEOUT);
  108. #
  109. # now we set things up for the real work
  110. # and fire up the request
  111. #
  112. $ua = new LWP::UserAgent;
  113. $ua->agent("Nagios/0.1 " . $ua->agent);
  114. $urlstring = "http://" . $opt_H . $opt_u . $autostring;
  115. $url = url($urlstring);
  116. my $req = new HTTP::Request 'GET', $url;
  117. my $res = $ua->request($req);
  118. #
  119. # hopefully we´ve got something usefull
  120. #
  121. if ($res->is_success) {
  122. if($opt_l) {
  123. foreach $_ (split /^/m, $res->content) {
  124. next if /^\s*$/;
  125. #
  126. # this is the load checking section
  127. # we parse the whole content, just in case someone
  128. # wants to use this some day in the future
  129. #
  130. if (/^Total Accesses:\s+([0-9.]+)/) { $accesses = $1; next; }
  131. if (/^Total kBytes:\s+([0-9.]+)/) { $kbytes = $1; next; }
  132. if (/^CPULoad:\s+([0-9.]+)\s+/) { $load = $1; next; }
  133. if (/^Uptime:\s+([0-9.]+)\s+/) { $uptime = $1; next; }
  134. if (/^ReqPerSec:\s+([0-9.]+)\s+/) { $rps = $1; next; }
  135. if (/^BytesPerSec:\s+([0-9.]+)\s+/) { $bps = $1; next; }
  136. if (/^BytesPerReq:\s+([0-9.]+)\s+/) { $bpr = $1; next; }
  137. if (/^BusyServers:\s+([0-9.]+)\s+/) { $busy = $1; next; }
  138. if (/^IdleServers:\s+([0-9.]+)\s+/) { $idle = $1; next; }
  139. if (/^Scoreboard:\s+([SRWKDLG_.]+)\s+/) { $score = $1; next; }
  140. print "Unknown Status\n";
  141. exit $ERRORS{"UNKNOWN"};
  142. }
  143. #
  144. # now we even parse the whole scoreboard, just for fun
  145. #
  146. foreach $scorepoint (split //m, $score) {
  147. if($scorepoint eq '.') { $scores{'.'}+=1; next; } # Unused
  148. if($scorepoint eq '_') { $scores{'_'}+=1; next; } # Waiting
  149. if($scorepoint eq 'S') { $scores{'S'}+=1; next; } # Starting
  150. if($scorepoint eq 'R') { $scores{'R'}+=1; next; } # Reading
  151. if($scorepoint eq 'W') { $scores{'W'}+=1; next; } # Writing
  152. if($scorepoint eq 'K') { $scores{'K'}+=1; next; } # Keepalive
  153. if($scorepoint eq 'D') { $scores{'D'}+=1; next; } # DNS Lookup
  154. if($scorepoint eq 'L') { $scores{'L'}+=1; next; } # Logging
  155. if($scorepoint eq 'G') { $scores{'G'}+=1; next; } # Going
  156. }
  157. if($busy>$alert) {
  158. printf "HTTPD CRITICAL: %.0f servers running\n", $busy;
  159. exit $ERRORS{"CRITICAL"};
  160. }
  161. if($busy>$warn) {
  162. printf "HTTPD WARNING: %.0f servers running\n", $busy;
  163. exit $ERRORS{"WARNING"};
  164. }
  165. printf "HTTPD ok: %.0f servers running, %d idle\n", $busy, $idle;
  166. exit $ERRORS{"OK"};
  167. } else {
  168. #
  169. # this is the performance check section
  170. # We are a bit lazy here, no parsing of the initial data
  171. # block and the scoreboard.
  172. # However, you have the whole set of per server
  173. # information to play with ;-)
  174. # The actual performance is measured by adding up the
  175. # milliseconds required to process the most recent
  176. # requests of all instances and then taking the average.
  177. #
  178. foreach $tablerow (split /<tr>/m, $res->content) {
  179. ($empty,$Srv,$PID,$Acc,$M,$CPU,$SS,$Req,$Conn,$Child,$Slot,$Client,$VHost,$Request)
  180. = split /<td>/, $tablerow;
  181. if($Req) {
  182. $lines+=1;
  183. $req_sum+=$Req;
  184. }
  185. undef $Req;
  186. }
  187. $average=$req_sum/$lines;
  188. if($average>$alert) {
  189. printf "HTTPD CRITICAL: average response time %.0f
  190. milliseconds\n", $average;
  191. exit $ERRORS{"CRITICAL"};
  192. }
  193. if($average>$warn) {
  194. printf "HTTPD WARNING: average response time %.0f
  195. milliseconds\n", $average;
  196. exit $ERRORS{"WARNING"};
  197. }
  198. if($average>0) {
  199. printf "HTTPD ok: average response time %.0f milliseconds\n",
  200. $average;
  201. exit $ERRORS{"OK"};
  202. }
  203. print "Unknown Status\n";
  204. exit $ERRORS{"UNKNOWN"};
  205. }
  206. } else {
  207. print "HTTP request failed\n";
  208. exit $ERRORS{"CRITICAL"};
  209. }
  210. #
  211. # ok, now we are almost through
  212. # These last subroutines do the things for those that do not
  213. # read source code.
  214. #
  215. sub print_usage () {
  216. print "Usage: $0 -H <host> [-lhV] [-w <warn>] [-c <crit>] [-u <url>]\n"; }
  217. sub print_help () {
  218. print "\n";
  219. print "\n";
  220. print "check_apache nagios plugin version $version\n";
  221. print "\n";
  222. print "The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n";
  223. print "copies of the plugins under the terms of the GNU General Public License.\n";
  224. print "For more information about these matters, see the file named COPYING.\n";
  225. print "\n";
  226. print "Copyright (c) 2001 Sebastian Hetze Linux Information Systems AG\n";
  227. print "\n";
  228. print "\n";
  229. print "This plugin checks the apache HTTP service on the specified host.\n";
  230. print "It uses the mod_status facilities provided by the apache server.\n";
  231. print "The monitoring server must be authorized in httpd.conf.\n";
  232. print "\n";
  233. print "\n";
  234. print_usage();
  235. print "\n";
  236. print "Options:\n";
  237. print " -H, --hostname=ADDRESS\n";
  238. print " host name argument for server.\n";
  239. print " -l, --load\n";
  240. print " check load instead of performance.\n";
  241. print " -h, --help\n";
  242. print " print detailed help screen.\n";
  243. print " -V, --version\n";
  244. print " print version information.\n";
  245. print " -w, --warning=INTEGER\n";
  246. print " load / performance level at which a warning message will be gererated.\n";
  247. print " -c, --critical=INTEGER\n";
  248. print " load / performance level at which a critical message will be gererated.\n";
  249. print " -u, --url=PATH\n";
  250. print " location to call mod_status.\n";
  251. print "\n";
  252. print " Defaults for performance checking are $perf_w/$perf_c msec.\n";
  253. print " Defaults for load checking are $load_w/$load_c servers running.\n";
  254. print "\n";
  255. print "\n";
  256. }
  257. #
  258. # the end
  259. #