-*- 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.
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 ]
<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>
<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>
<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
#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];
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) {
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(<, apr_time_now());
+ utc_offset = lt.tm_gmtoff;
+ }
+ tLogStart = (int)apr_time_sec(apr_time_now()) + utc_offset;
}
if (use_strftime) {