Hi,
Here is a patch for monit/protocols/http.c, based in the 4.4 release.
With this patch
Monit will check the status of an Apache server using the mod_status
page
available at
http://www.example.com/server-status/?auto
to see if logging is working successfully.
If there are more than 50% of active httpd processes logging (i.e.
there is a problem with
logging) then the server is re-started. I was originally thinking
about a chroot specific
problem, but this patch is completely general. Other status messages
could also be
checked, as well as the ones about logging.
The /etc/monitrc entry looks like this:
if failed host 127.0.0.1 port 80
protocol HTTP request /server-status/?auto then restart
I have tested it, and it seems to work well. The original behaviour
of http.c is retained
for any other page request given in the monitrc file. During testing
I have found that if httpd processes become locked because they can't
log,
a request for server-status generates a new child process, and gives
a correct report on
the condition of the server. Only if there are very rapid incoming
connections or a very
low maximum number of httpd processes will the server-status page
become inaccessible. In
this case the server will be re-started because the connection to it
will fail.
I hope this is useful to people running Monit and Apache to avoid
server lock-up if
logging fails. If people don't want to include it in the Monit
distribution, I can put in
on my website for people to download.
Best wishes,
David.
diff -Naur http.c http_apache.c
--- http.c Sat Dec 4 00:21:34 2004
+++ http_apache.c Sat Dec 4 00:32:40 2004
@@ -60,6 +60,7 @@
static int check_request(Socket_T s);
static char *get_host_header(Socket_T s, char * host);
static int check_request_checksum(Socket_T s, char *checksum, int);
+static int check_apache_status(Socket_T s);
/**
@@ -113,8 +114,12 @@
if(request_checksum) {
return check_request_checksum(s, request_checksum,
request_hashtype);
}
-
- return check_request(s);
+ + if(strcmp(request, "/server-status/?auto")){
+ return check_request(s);
+ }else{
+ return check_apache_status(s);
+ }
}
@@ -276,3 +281,75 @@
return TRUE;
}
+
+
+
+/**
+ * Check an Apache server to detect logging difficulties
+ * Do this using the server-status report, which will only be
+ * available if the server is still responding to some extent.
+ * Could be expanded to monitor other server-status messages.
+ * @param s A socket
+ * @return TRUE if the respons is valid otherwise FALSE
+ */
+static int check_apache_status(Socket_T s) {
+ + char line[STRLEN];
+ char search_string[STRLEN];
+ int scored = 0;
+ + if(! check_request(s))
+ return FALSE;
+ + while(NULL != socket_readln(s, line, STRLEN)) {
+ if(starts_with(line, "Scoreboard:")) { + if(1 !=
sscanf(line, "%*s%*[: ]%s", search_string)) {
+ chomp(line, STRLEN);
+ log("HTTP error: parsing Apache status response '%s'\n", line);
+ return FALSE;
+ }else{
+ scored = 1;
+ }
+ }
+ }
+ + DEBUG("Scoreboard: %s\n", search_string);
+ + /*Check that some scoreboard line was found, if not return an
error*/
+ if(!scored){
+ log("HTTP error: no scoreboard line returned by Apache
server-status\n");
+ return FALSE;
+ }
+ + int no_L,active_servers;
+ double logging;
+ char *p;
+ + /*Percentage of Apache child processes that may be logging
before a restart*/
+ double logging_limit = 50;
+ + no_L = 0;
+ active_servers = 0;
+ + /*Currently only logging processes, further types could be
added*/
+ for(p = search_string ; *p ; p++){
+ active_servers++;
+ switch(*p){
+ case 'L':
+ no_L++;
+ break;
+ case '.':
+ active_servers--;
+ break;
+ }
+ }
+ + logging = 100 * no_L / active_servers;
+ + if(logging > logging_limit){
+ log("HTTP error: %3.0f percent of Apache processes are
logging\n", logging);
+ return FALSE;
+ } + return TRUE;
+}
+