add -T flag to truncate rotated logs only

for strftime formats that will loop back on themselves, like
day of month or weekday name.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1906433 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Eric Covener
2023-01-06 23:46:35 +00:00
parent 43f0c91fd0
commit d0eac89e98
3 changed files with 42 additions and 6 deletions

View File

@ -0,0 +1,2 @@
*) rotatelogs: Add -T flag to allow subsequent rotated logfiles to be
truncated without the initial logfile being truncated. [Eric Covener]

View File

@ -111,6 +111,13 @@ the filename, however format strings containing '%' characters
will be respected.
</dd>
<dt><code>-T</code></dt>
<dd>Causes all but the initial logfile to be truncated when opened.
This is useful when the format string contains something that will
loop around, such as the day of the month.
</dd>
<dt><code>-v</code></dt>
<dd>Produce verbose output on STDERR. The output contains
the result of the configuration parsing, and all file open and
@ -263,6 +270,18 @@ an offset.</dd>
in this scenario that a separate process (such as tail) would
process the file in real time.</p>
<example>
<highlight language="config">
CustomLog "|bin/rotatelogs -T /var/log/logfile.%d 86400" common
</highlight>
</example>
<p>If the server is started (or restarted) on the first of the month, this
appends to <code>/var/log/logfile.01</code>. When a log entry is written on the
second of the month, <code>/var/log/logfile.02</code> is truncated and new entries
will be added to the top. This example keeps approximately 1 months worth of
logs without external maintenance.</p>
</section>
<section id="portability"><title>Portability</title>

View File

@ -65,6 +65,7 @@ struct rotate_config {
int echo;
char *szLogRoot;
int truncate;
int truncate_rotated_only;
const char *linkfile;
const char *postrotate_prog;
#if APR_FILES_AS_SOCKETS
@ -109,9 +110,9 @@ static void usage(const char *argv0, const char *reason)
}
fprintf(stderr,
#if APR_FILES_AS_SOCKETS
"Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-D] [-t] [-e] [-c] [-n number] <logfile> "
"Usage: %s [-vlfDtTec] [-L linkname] [-p prog] [-n number] <logfile> "
#else
"Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-D] [-t] [-e] [-n number] <logfile> "
"Usage: %s [-vlfDtTe] [-L linkname] [-p prog] [-n number] <logfile> "
#endif
"{<rotation time in seconds>|<rotation size>(B|K|M|G)} "
"[offset minutes from UTC]\n\n",
@ -145,6 +146,7 @@ static void usage(const char *argv0, const char *reason)
" -f Force opening of log on program start.\n"
" -D Create parent directories of log file.\n"
" -t Truncate logfile instead of rotating, tail friendly.\n"
" -T Truncate logfiles opened for rotation, but not the initial logfile.\n"
" -e Echo log to stdout for further processing.\n"
#if APR_FILES_AS_SOCKETS
" -c Create log even if it is empty.\n"
@ -379,6 +381,7 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
struct logfile newlog;
int thisLogNum = -1;
int oldreason = status->rotateReason;
int truncate = config->truncate;
/* Retrieve local-time-adjusted-Unix-time. */
now = get_now(config, &offset);
@ -458,8 +461,17 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
if (config->verbose) {
fprintf(stderr, "Opening file %s\n", newlog.name);
}
rv = apr_file_open(&newlog.fd, newlog.name, APR_WRITE | APR_CREATE | APR_APPEND
| (config->truncate || (config->num_files > 0 && status->current.fd) ? APR_TRUNCATE : 0),
if (!truncate) {
/* -n and -T truncate subsequent files only. */
if (status->current.fd &&
(config->num_files > 0 || config->truncate_rotated_only)) {
truncate = 1;
}
}
rv = apr_file_open(&newlog.fd, newlog.name,
APR_WRITE | APR_CREATE | APR_APPEND
| (truncate ? APR_TRUNCATE : 0),
APR_OS_DEFAULT, newlog.pool);
if (rv == APR_SUCCESS) {
/* Handle post-rotate processing. */
@ -597,9 +609,9 @@ int main (int argc, const char * const argv[])
apr_pool_create(&status.pool, NULL);
apr_getopt_init(&opt, status.pool, argc, argv);
#if APR_FILES_AS_SOCKETS
while ((rv = apr_getopt(opt, "lL:p:fDtvecn:", &c, &opt_arg)) == APR_SUCCESS) {
while ((rv = apr_getopt(opt, "lL:p:fDtTvecn:", &c, &opt_arg)) == APR_SUCCESS) {
#else
while ((rv = apr_getopt(opt, "lL:p:fDtven:", &c, &opt_arg)) == APR_SUCCESS) {
while ((rv = apr_getopt(opt, "lL:p:fDtTven:", &c, &opt_arg)) == APR_SUCCESS) {
#endif
switch (c) {
case 'l':
@ -624,6 +636,9 @@ int main (int argc, const char * const argv[])
case 't':
config.truncate = 1;
break;
case 'T':
config.truncate_rotated_only = 1;
break;
case 'v':
config.verbose = 1;
break;