From new-httpd-return-18272-apmail-new-httpd-archive=apache.org@apache.org Wed Aug 01 23:17:19 2001 Return-Path: Delivered-To: apmail-new-httpd-archive@apache.org Received: (qmail 82283 invoked by uid 500); 1 Aug 2001 23:17:18 -0000 Mailing-List: contact new-httpd-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list new-httpd@apache.org Received: (qmail 82272 invoked from network); 1 Aug 2001 23:17:17 -0000 Sender: chuck@mail2.state.tn.us Message-ID: <3B688D3A.B3894CC3@onyxsys.net> Date: Wed, 01 Aug 2001 18:14:02 -0500 From: Chuck Pierce X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.6 i686) X-Accept-Language: en MIME-Version: 1.0 To: new-httpd@apache.org Subject: splitlogs Content-Type: multipart/mixed; boundary="------------3241FB56AF487BB7D28F35FA" X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N Status: O X-Status: X-Keywords: X-UID: 29 This is a multi-part message in MIME format. --------------3241FB56AF487BB7D28F35FA Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit I'm new to the list, so I don't quite know the procedure for doing this , but I have attached a program that I think the apache community could benefit from. The program is self reliant, and will split the apache log files on the fly (it will also rotate the logs). ---- History: Our web site is huge. It has one domain and a BUNCH of sub directories. Each sub directory needed to act as a separate "virtual host". Because I couldn't have the customelog or transferlog within a I created this app. It allows me (using the tags) to create a sub directory in www.mycompany.com/subdir and have it's own logfile. ---- Usage: splitlogs [OPTIONS]... DEFAULT... Where OPTIONS can be FILE:DIRECTORY:ROTATION or FILE:DIRECTORY DEFAULT is in the format FILE:ROTATION or FILE The FILE is the path and name of the actual logfile. The DIRECTORY is the directory you want split into a separate file. The ROTATION is the system time at which the log will be rotated. If no ROTATION time is given, the log will not be rotated and the file name will remain unchanged. If rotation is used, the log file will be in the format: FILE.2001_Aug_01_17:55.log Installation: Add the following to the httpd.conf: TransferLog "| splitlogs log-A:/A:86400 log-B:/B log-def Note: If you have the two directories /a and /a/b, make sure to place the /a/b before /a. Otherwise all of the /a/b requests would end up in the wrong logfile. -- Chuck Pierce Phone: (615) 253-5634 Sr. Systems Administrator Pager: (888) 569-8085 State TN, OIR/Finance Fax: (615) 741-7341 --------------3241FB56AF487BB7D28F35FA Content-Type: text/plain; charset=us-ascii; name="splitlogs.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="splitlogs.c" /* * A program to split the output of a logfile on the fly and rotate (if necessary) * * Contributed by Chuck Pierce * * Aug 01, 2001 */ #include #include #include #include #include #define NAME "splitlogs" #define VERSION "1.0a" #define BUFSIZE 65536 #ifndef utc_offset #define utc_offset 0 #endif struct darray { char **data; int count; }; struct options { char *dir; /* Directory in the url */ char *file; /* Location of the logfile */ char *ofile; /* Unmodified name of the file */ int FOUT; /* File pointer */ int rotate; /* Rotation time . */ }; struct darray *SPLIT(char *data, char *delim) { /* a function for spliting a string into an array of strings */ char *ptr = data, *fptr = data, **array = NULL, *string; int j, i, len, counter = 0; struct darray *output; output = calloc(sizeof(struct darray *), counter); if (output == NULL) { fprintf(stderr, "Error: out of memory\n"); exit(0); } /* if there is nothing to split, there is no need to try to split it */ if (!data) { output->count = 0; return output; } /* find out how big we need to be */ do { ptr = strstr(ptr, delim); if (ptr) { ptr = ptr + strlen(delim); } counter++; } while (ptr); /* split */ ptr = data; array = calloc(sizeof(char **), counter); if (array == NULL) { fprintf(stderr, "Error: out of memory\n"); exit(0); } for (j=0; jdata = array; output->count = counter; return (output); } int main (int argc, char **argv) { char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /* Get the date/time */ time_t timep = time(NULL) + utc_offset, logtimep = timep; struct tm *date = localtime(&timep); char line[BUFSIZE], *bptr, *fptr; int i = 0, nread, nwrite; struct options **list, *item; struct darray *parced; if ((argc < 2) || !strcmp(argv[1], "-h") || !strcmp(argv[1], "-help") || !strcmp(argv[1], "--help")) { fprintf(stderr, "%s, version %s\n\n" "Usage: %s [OPTIONS]... DEFAULT...\n" "\n" " Where OPTIONS can be FILE:DIRECTORY:ROTATION or FILE:DIRECTORY\n" "\n" " DEFAULT is in the format FILE:ROTATION or FILE\n" "\n" " The FILE is the path and name of the actual logfile. The DIRECTORY\n" " is the directory you want split into a separate file. The ROTATION\n" " is the system time at which the log will be rotated. If no\n" " ROTATION time is given, the log will not be rotated and the file\n" " name will remain unchanged. If rotation is used, the log file will\n" " be in the format: FILE.%0.4d_%s_%0.2d_%0.2d:%0.2d.log\n" "\n" "\n" "Installation:\n" " Add the following to the httpd.conf:\n" "\n" "TransferLog \"|%s log-A:/A:86400 log-B:/B log-def\n" "\n" "\n" "Note: If you have the two directories /a and /a/b, make sure to place\n" " the /a/b before /a. Otherwise all of the /a/b requests would\n" " end up in the wrong logfile.\n" , NAME, VERSION, NAME, date->tm_year + 1900, months[date->tm_mon], date->tm_mday, date->tm_hour, date->tm_min, argv[0]); exit(1); } list = calloc(sizeof(struct options **), argc); if (list == NULL) { fprintf(stderr, "Error: out of memory\n"); exit(0); } /* Build the array of options, fill the list and open the files */ for (i=0; idata[0] && strlen(parced->data[0])) { item->ofile = parced->data[0]; } else { fprintf(stderr, "Invalad usage. Try using %s --help\n", argv[0]); exit(1); } if (parced->data[1] && strlen(parced->data[1]) && (i != (argc - 1))) { item->dir = calloc(sizeof(char *), strlen(parced->data[1]) + 6); sprintf(item->dir, " \"GET %s", parced->data[1]); } else { item->dir = NULL; } if (parced->data[2]) { item->file = calloc(sizeof(char *), strlen(item->ofile) + 21); sprintf(item->file, "%s.%0.4d_%s_%0.2d_%0.2d:%0.2d.log", item->ofile, date->tm_year + 1900, months[date->tm_mon], date->tm_mday, date->tm_hour, date->tm_min); item->rotate = atoi(parced->data[2]); } else { if ((i == (argc - 2)) && parced->data[1] && strlen(parced->data[1])) { item->file = calloc(sizeof(char *), strlen(item->ofile) + 21); sprintf(item->file, "%s.%0.4d_%s_%0.2d_%0.2d:%0.2d.log", item->ofile, date->tm_year + 1900, months[date->tm_mon], date->tm_mday, date->tm_hour, date->tm_min); item->rotate = atoi(parced->data[1]); } else { item->file = item->ofile; item->rotate = 0; } } item->FOUT = open(item->file, O_WRONLY | O_CREAT | O_APPEND, 0640); if (item->FOUT < 0) { fprintf(stderr, "Error opening file %s\n", item->file); exit(2); } list[i] = item; } /* Main Loop */ for (;;) { /* Read the log entery */ nread = read(0, line, sizeof line); if (nread <= 0) { /* If this hapens, the program needs to quit */ exit(3); } timep = time(NULL) + utc_offset; /* Go through each directory and see which one gets the log entry */ for (i=0; idir && strstr(line, list[i]->dir)) || (i == (argc - 2))) { if (list[i]->rotate && (timep >= (logtimep + list[i]->rotate))) { /* It's time to rotate the log */ close(list[i]->FOUT); logtimep = timep; date = localtime(&timep); sprintf(list[i]->file, "%s.%0.4d_%s_%0.2d_%0.2d:%0.2d.log", list[i]->ofile, date->tm_year + 1900, months[date->tm_mon], date->tm_mday, date->tm_hour, date->tm_min); list[i]->FOUT = open(list[i]->file, O_WRONLY | O_CREAT | O_APPEND, 0640); if (list[i]->FOUT < 0) { fprintf(stderr, "Error opening file %s\n", list[i]->file); exit(2); } } do { nwrite = write(list[i]->FOUT, line, nread); } while (nwrite < 0); if (nread != nwrite) { fprintf(stderr, "Error writing to file %s.", list[i]->file); exit(2); } break; } } } /* Suppress compiler warning */ return (0); } --------------3241FB56AF487BB7D28F35FA--