/* ==================================================================== * Copyright (c) 1995-1997 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see . * simple script to monitor the child Apache processes * Usage: * httpd_monitor [ -d serverdir | -f conffile ] [ -s sleep_time ] * -d/-f options specify server dir or config files, as per * httpd. * -s specifies how long to pause between screen updates * If you choose 0, it might chew up lots of CPU time. * * Output explanation.. * * s = sleeping but "ready to go" child (this is '_' in mod_status) * R = active child - writing to client * W = active child - reading from client * K = active child - waiting for additional request on kept-alive connection * D = active child - doing DNS lookup * L = active child - logging * _ = dead child (no longer needed) (this is '.' in mod_status) * t = just starting (this is 'S' in mod_status) * * * Jim Jagielski * v1.0 Notes: * This code is much more ugly and complicated than it * needs to be. * * v1.1: * Minor fixes * * v1.2: * Handles Apache 1.1.* scoreboard format (W/K/D/L states) -- PCS 09Jul96 */ #include #include #include #include #include "../src/httpd.h" #include "../src/scoreboard.h" #define DEFAULT_SLEEPTIME 2 #define ASIZE 1024 #define MAX_PROC HARD_SERVER_LIMIT int main(argc, argv) int argc; char **argv; { short_score scoreboard_image; FILE *afile; char conf_name[ASIZE]; char pid_name[ASIZE]; char score_name[ASIZE]; char tbuf[ASIZE]; char *ptmp; static char kid_stat[] = { '_', 's', 'R', 't', 'W', 'K', 'L', 'D' }; int achar; long thepid; int score_fd; int sleep_time = DEFAULT_SLEEPTIME; int last_len = 0; int kiddies; int running, dead, total, loop; short got_config = 0; struct stat statbuf; time_t last_time = 0; extern char *optarg; extern int optind, opterr; void lookfor(); int usage(); /* * Handle the options. Using getopt() is most probably overkill, * but let's think about the future! */ strcpy(conf_name, HTTPD_ROOT); while((achar = getopt(argc,argv,"s:d:f:")) != -1) { switch(achar) { case 'd': strcpy(conf_name, optarg); break; case 'f': strcpy(conf_name, optarg); got_config = 1; break; case 's': sleep_time = atoi(optarg); break; case '?': usage(argv[0]); } } /* * Now build the name of the httpd.conf file */ if (!got_config) { strcat(conf_name, "/"); strcat(conf_name, SERVER_CONFIG_FILE); } /* * Make sure we have the right file... Barf if not */ if (!(afile = fopen(conf_name, "r"))) { perror("httpd_monitor"); fprintf(stderr, "Can't open config file: %s\n", conf_name); exit(1); } /* * now scan thru the ConfigFile to look for the items that * interest us */ lookfor(pid_name, score_name, afile); fclose(afile); /* * now open the PidFile and then the ScoreBoardFile */ if (!(afile = fopen(pid_name, "r"))) { perror("httpd_monitor"); fprintf(stderr, "Can't open PIDfile: %s\n", pid_name); exit(1); } fscanf(afile, "%ld", &thepid); fclose(afile); /* * Enough taters, time for the MEAT! */ for(;;sleep(sleep_time)) { if (stat(score_name, &statbuf)) { perror("httpd_monitor"); fprintf(stderr, "Can't stat scoreboard file: %s\n", score_name); exit(1); } if (last_time == statbuf.st_mtime) continue; /* tricky ;) */ last_time = statbuf.st_mtime; /* for next time */ if ((score_fd = open(score_name, 0)) == -1 ) { perror("httpd_monitor"); fprintf(stderr, "Can't open scoreboard file: %s\n", score_name); exit(1); } /* * all that for _this_ */ running = dead = total = 0; ptmp = tbuf; *ptmp = '\0'; for(kiddies=0;kiddies strlen(tbuf)) { for(loop=1;loop<=last_len;loop++) putchar(' '); for(loop=1;loop<=last_len;loop++) putchar('\010'); } printf("%s", tbuf); fflush(stdout); last_len = strlen(tbuf); } /* for */ } int usage(arg) char *arg; { printf("httpd_monitor: Usage\n"); printf(" httpd_monitor [ -d config-dir] [ -s sleep-time ]\n"); printf(" Defaults: config-dir = %s\n", HTTPD_ROOT); printf(" sleep-time = %d seconds\n", DEFAULT_SLEEPTIME); exit(0); } /* * This function uses some hard-wired knowledge about the * Apache httpd.conf file setup (basically names of the 3 * parameters we are interested in) * * We basically scan thru the file and grab the 3 values we * need. This could be done better... */ void lookfor(pidname, scorename, thefile) char *pidname, *scorename; FILE *thefile; { char line[ASIZE], param[ASIZE], value[ASIZE]; char sroot[ASIZE], pidfile[ASIZE], scorefile[ASIZE]; *sroot = *pidfile = *scorefile = '\0'; while (!(feof(thefile))) { fgets(line, ASIZE-1, thefile); *value = '\0'; /* protect braindead sscanf() */ sscanf(line, "%s %s", param, value); if (strcmp(param, "PidFile")==0 && *value) strcpy(pidfile, value); if (strcmp(param, "ScoreBoardFile")==0 && *value) strcpy(scorefile, value); if (strcmp(param, "ServerRoot")==0 && *value) strcpy(sroot, value); } /* * We've reached EOF... we should have encountered the * ServerRoot line... if not, we bail out */ if (!*sroot) { fprintf(stderr, "Can't find ServerRoot!\n"); exit(1); } /* * Not finding PidFile or ScoreBoardFile is OK, since * we have defaults for them */ if (!*pidfile) strcpy(pidfile, DEFAULT_PIDLOG); if (!*scorefile) strcpy(scorefile, DEFAULT_SCOREBOARD); /* * Relative or absolute? Handle both */ if (*pidfile == '/') strcpy(pidname, pidfile); else { strcpy(pidname, sroot); strcat(pidname, "/"); strcat(pidname, pidfile); } if (*scorefile == '/') strcpy(scorename, scorefile); else { strcpy(scorename, sroot); strcat(scorename, "/"); strcat(scorename, scorefile); } }