]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
super cool rotatelogs enhancements
authorJim Jagielski <jim@apache.org>
Mon, 26 Nov 2007 13:50:03 +0000 (13:50 +0000)
committerJim Jagielski <jim@apache.org>
Mon, 26 Nov 2007 13:50:03 +0000 (13:50 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@598272 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
docs/manual/programs/rotatelogs.xml
support/rotatelogs.c

diff --git a/CHANGES b/CHANGES
index 6860af1b1a019abb473f76c746c95902aef3806e..d7d49aea519fb00d5e1485412ad3ab47dda1d8f3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                         -*- coding: utf-8 -*-
 Changes with Apache 2.2.7
 
+  *) rotatelogs: Change command-line parsing to report more types
+     of errors.  Allow local timestamps to be used when rotating based
+     on file size.  [Jeff Trawick]
+
   *) mod_proxy: Canonicalisation improvements. Add "nocanon" keyword to
      ProxyPass, to suppress URI-canonicalisation in a reverse proxy. Also,
      don't escape/unescape forward-proxied URLs.
diff --git a/STATUS b/STATUS
index ae07be2d247562e1b956ab20b5cc19940d49aeb7..29b55df6aa4290ce66d69972f0808d568793068d 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -79,18 +79,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-   * rotatelogs: Change command-line parsing to report more types
-     of errors.  Allow local timestamps to be used when rotating based
-     on file size.
-     trunk:
-         http://svn.apache.org/viewvc?view=rev&revision=596698
-         http://svn.apache.org/viewvc?view=rev&revision=596796
-         http://svn.apache.org/viewvc?view=rev&revision=596830
-         http://svn.apache.org/viewvc?view=rev&revision=596884
-     2.2.x:
-         Trunk patches apply, but here is a consolidated patch:
-         http://people.apache.org/~trawick/rotatelogs.txt
-     +1: trawick, rpluem, jim
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index 86ebb94476a3569548d22497efac5f66bf4168f6..acfae444f5830597aaf0bbbe31d5cf351d6b3d23 100644 (file)
 
 <summary>
      <p><code>rotatelogs</code> is a simple program for use in
-     conjunction with Apache's piped logfile feature.  For example:</p>
-
-<example>
-     CustomLog "|bin/rotatelogs /var/logs/logfile 86400" common
-</example>
-        
-     <p>This creates the files /var/logs/logfile.nnnn where nnnn  is
-     the system time at which the log nominally starts (this time
-     will always be a multiple of the rotation time, so  you  can
-     synchronize cron scripts with it).  At the end of each rotation
-     time (here after 24 hours) a new log is started.</p>
-
-<example>
-     CustomLog "|bin/rotatelogs /var/logs/logfile 5M" common
-</example>
-
-     <p>This configuration will rotate the logfile whenever it reaches
-     a size of 5 megabytes.</p>
-
-<example>
-     ErrorLog "|bin/rotatelogs /var/logs/errorlog.%Y-%m-%d-%H_%M_%S 5M"
-</example>
-     <p>This configuration will rotate the error logfile whenever it
-     reaches a size of 5 megabytes, and the suffix to the logfile name
-     will be created of the form
-     <code>errorlog.YYYY-mm-dd-HH_MM_SS</code>.</p>
+     conjunction with Apache's piped logfile feature.  It supports
+     rotation based on a time interval or maximum size of the log.</p>
 </summary>
 
 <section id="synopsis"><title>Synopsis</title>
@@ -61,8 +36,8 @@
      <p><code><strong>rotatelogs</strong>
      [ -<strong>l</strong> ]
      <var>logfile</var>
-     [ <var>rotationtime</var> [ <var>offset</var> ]] |
-     [ <var>filesize</var>M ]</code></p>
+     <var>rotationtime</var>|<var>filesize</var>M 
+     [ <var>offset</var> ]</code></p>
 </section>
 
 <section id="options"><title>Options</title>
 
 <dt><code>-l</code></dt>
 <dd>Causes the use of local time rather than GMT as the base for the
-interval. Note that using <code>-l</code> in an environment which changes the
-GMT offset (such as for BST or DST) can lead to unpredictable results!</dd>
+interval or for <code>strftime(3)</code> formatting with size-based 
+rotation.  Note that using <code>-l</code> in an environment which
+changes the GMT offset (such as for BST or DST) can lead to unpredictable
+results!</dd>
 
 <dt><code><var>logfile</var></code></dt>
 
@@ -81,26 +58,73 @@ includes any '%' characters, it is treated as a format string for
 <code>strftime(3)</code>.  Otherwise, the suffix
 <var>.nnnnnnnnnn</var> is automatically added and is the time in
 seconds.  Both formats compute the start time from the beginning of
-the current period.</dd>
+the current period.  For example, if a rotation time of 86400 is 
+specified, the hour, minute, and second fields created by
+<code>strftime(3)</code> format will all be zero, referring to the
+beginning of the current 24-hour period (midnight).</dd>
 
 <dt><code><var>rotationtime</var></code></dt>
 
-<dd>The time between log file rotations in seconds.</dd>
+<dd>The time between log file rotations in seconds.  The rotation
+occurs at the beginning of this interval.  For example, if the
+rotation time is 3600, the log file will be rotated at the beginning
+of every hour; if the rotation time is 86400, the log file will be
+rotated every night at midnight.  (If no data is logged during an
+interval, no file will be created.)</dd>
+
+<dt><code><var>filesize</var>M</code></dt>
+
+<dd>The maximum file size in megabytes followed by the letter
+<code>M</code> to specify size rather than time.</dd>
 
 <dt><code><var>offset</var></code></dt>
 
 <dd>The number of minutes offset from UTC.  If omitted, zero is
 assumed and UTC is used.  For example, to use local time in the zone
-UTC -5 hours, specify a value of <code>-300</code> for this argument.</dd>
-
-<dt><code><var>filesize</var>M</code></dt>
+UTC -5 hours, specify a value of <code>-300</code> for this argument.
+In most cases, <code>-l</code> should be used instead of specifying
+an offset.</dd>
 
-<dd>The maximum file size in megabytes followed by the letter
-<code>M</code> to specify size rather than time.  Use this parameter
-in place of both rotationtime and offset.</dd>
 </dl>
 </section>
 
+<section id="examples"><title>Examples</title>
+
+<example>
+     CustomLog "|bin/rotatelogs /var/logs/logfile 86400" common
+</example>
+        
+     <p>This creates the files /var/logs/logfile.nnnn where nnnn  is
+     the system time at which the log nominally starts (this time
+     will always be a multiple of the rotation time, so  you  can
+     synchronize cron scripts with it).  At the end of each rotation
+     time (here after 24 hours) a new log is started.</p>
+
+<example>
+     CustomLog "|bin/rotatelogs -l /var/logs/logfile.%Y.%m.%d 86400" common
+</example>
+        
+     <p>This creates the files /var/logs/logfile.yyyy.mm.dd where
+     yyyy is the year, mm is the month, and dd is the day of the month.
+     Logging will switch to a new file every day at midnight, local time.</p>
+
+<example>
+     CustomLog "|bin/rotatelogs /var/logs/logfile 5M" common
+</example>
+
+     <p>This configuration will rotate the logfile whenever it reaches
+     a size of 5 megabytes.</p>
+
+<example>
+     ErrorLog "|bin/rotatelogs /var/logs/errorlog.%Y-%m-%d-%H_%M_%S 5M"
+</example>
+     <p>This configuration will rotate the error logfile whenever it
+     reaches a size of 5 megabytes, and the suffix to the logfile name
+     will be created of the form
+     <code>errorlog.YYYY-mm-dd-HH_MM_SS</code>.</p>
+</section>
+
 <section id="portability"><title>Portability</title>
 
 <p>The following logfile format string substitutions should be
index c6f990493858f0d46efccb34b256cb8051d3c7b0..a408540a1b6cdef93ced992602599f6f70a01b85 100644 (file)
@@ -42,6 +42,7 @@
 #include "apr_file_info.h"
 #include "apr_general.h"
 #include "apr_time.h"
+#include "apr_getopt.h"
 
 #if APR_HAVE_STDLIB_H
 #include <stdlib.h>
 #define MAX_PATH        1024
 #endif
 
+static void usage(const char *argv0, const char *reason)
+{
+    if (reason) {
+        fprintf(stderr, "%s\n", reason);
+    }
+    fprintf(stderr,
+            "Usage: %s [-l] <logfile> "
+            "{<rotation time in seconds>|<rotation size in megabytes>} "
+            "[offset minutes from UTC]\n\n",
+            argv0);
+#ifdef OS2
+    fprintf(stderr,
+            "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
+            argv0);
+#else
+    fprintf(stderr,
+            "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
+            argv0);
+    fprintf(stderr,
+            "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv0);
+#endif
+    fprintf(stderr,
+            "to httpd.conf. The generated name will be /some/where.nnnn "
+            "where nnnn is the\nsystem time at which the log nominally "
+            "starts (N.B. if using a rotation time,\nthe time will always "
+            "be a multiple of the rotation time, so you can synchronize\n"
+            "cron scripts with it). At the end of each rotation time or "
+            "when the file size\nis reached a new log is started.\n");
+    exit(1);
+}
+
 int main (int argc, const char * const argv[])
 {
     char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ];
@@ -73,71 +105,58 @@ int main (int argc, const char * const argv[])
     const char *szLogRoot;
     apr_file_t *f_stdin, *nLogFD = NULL, *nLogFDprev = NULL;
     apr_pool_t *pool;
+    apr_getopt_t *opt;
+    apr_status_t rv;
+    char c;
+    const char *optarg;
     char *ptr = NULL;
-    int argBase = 0;
-    int argFile = 1;
-    int argIntv = 2;
-    int argOffset = 3;
 
     apr_app_initialize(&argc, &argv, NULL);
     atexit(apr_terminate);
 
     apr_pool_create(&pool, NULL);
-    if ((argc > 2) && (strcmp(argv[1], "-l") == 0)) {
-        argBase++;
-        argFile += argBase;
-        argIntv += argBase;
-        argOffset += argBase;
-        use_localtime = 1;
+    apr_getopt_init(&opt, pool, argc, argv);
+    while ((rv = apr_getopt(opt, "l", &c, &optarg)) == APR_SUCCESS) {
+        switch (c) {
+        case 'l':
+            use_localtime = 1;
+            break;
+        }
     }
-    if (argc < (argBase + 3) || argc > (argBase + 4)) {
-        fprintf(stderr,
-                "Usage: %s [-l] <logfile> <rotation time in seconds> "
-                "[offset minutes from UTC] or <rotation size in megabytes>\n\n",
-                argv[0]);
-#ifdef OS2
-        fprintf(stderr,
-                "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
-                argv[0]);
-#else
-        fprintf(stderr,
-                "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
-                argv[0]);
-        fprintf(stderr,
-                "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv[0]);
-#endif
-        fprintf(stderr,
-                "to httpd.conf. The generated name will be /some/where.nnnn "
-                "where nnnn is the\nsystem time at which the log nominally "
-                "starts (N.B. if using a rotation time,\nthe time will always "
-                "be a multiple of the rotation time, so you can synchronize\n"
-                "cron scripts with it). At the end of each rotation time or "
-                "when the file size\nis reached a new log is started.\n");
-        exit(1);
+
+    if (rv != APR_EOF) {
+        usage(argv[0], NULL /* specific error message already issued */ );
+    }
+
+    if (opt->ind + 2 != argc && opt->ind + 3 != argc) {
+        usage(argv[0], "Incorrect number of arguments");
     }
 
-    szLogRoot = argv[argFile];
+    szLogRoot = argv[opt->ind++];
 
-    ptr = strchr(argv[argIntv], 'M');
-    if (ptr) {
+    ptr = strchr(argv[opt->ind], 'M');
+    if (ptr) { /* rotation based on file size */
         if (*(ptr+1) == '\0') {
-            sRotation = atoi(argv[argIntv]) * 1048576;
+            sRotation = atoi(argv[opt->ind]) * 1048576;
         }
         if (sRotation == 0) {
-            fprintf(stderr, "Invalid rotation size parameter\n");
-            exit(1);
+            usage(argv[0], "Invalid rotation size parameter");
         }
     }
-    else {
-        if (argc >= (argBase + 4)) {
-            utc_offset = atoi(argv[argOffset]) * 60;
-        }
-        tRotation = atoi(argv[argIntv]);
+    else { /* rotation based on elapsed time */
+        tRotation = atoi(argv[opt->ind]);
         if (tRotation <= 0) {
-            fprintf(stderr, "Rotation time must be > 0\n");
-            exit(6);
+            usage(argv[0], "Invalid rotation time parameter");
         }
     }
+    opt->ind++;
+
+    if (opt->ind < argc) { /* have UTC offset */
+        if (use_localtime) {
+            usage(argv[0], "UTC offset parameter is not valid with -l");
+        }
+        utc_offset = atoi(argv[opt->ind]) * 60;
+    }
 
     use_strftime = (strchr(szLogRoot, '%') != NULL);
     if (apr_file_open_stdin(&f_stdin, pool) != APR_SUCCESS) {
@@ -194,7 +213,16 @@ int main (int argc, const char * const argv[])
                 tLogStart = (now / tRotation) * tRotation;
             }
             else {
-                tLogStart = (int)apr_time_sec(apr_time_now());
+                if (use_localtime) {
+                    /* Check for our UTC offset before using it, since it might
+                     * change if there's a switch between standard and daylight
+                     * savings time.
+                     */
+                    apr_time_exp_t lt;
+                    apr_time_exp_lt(&lt, apr_time_now());
+                    utc_offset = lt.tm_gmtoff;
+                }
+                tLogStart = (int)apr_time_sec(apr_time_now()) + utc_offset;
             }
 
             if (use_strftime) {