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;
+}
+