summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Covener <covener@apache.org>2023-03-03 14:20:27 +0000
committerEric Covener <covener@apache.org>2023-03-03 14:20:27 +0000
commitcb6ad2f13850c3c68f78b233fcfadeac45125201 (patch)
treefee49f5ad4c7e36cba1a033da0ce371f529bc184
parent706538cafe99fac1d07e96d37660c0f655061aaa (diff)
downloadhttpd-cb6ad2f13850c3c68f78b233fcfadeac45125201.tar.gz
backport 1906428,1906433,1907993 from trunk
add rotatelogs -T to truncate all but the first-opened file. + docs tweak for compat git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1908025 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--changes-entries/rotatlogs_truncate_rotated.txt2
-rw-r--r--docs/manual/programs/rotatelogs.xml19
-rw-r--r--support/rotatelogs.c41
3 files changed, 56 insertions, 6 deletions
diff --git a/changes-entries/rotatlogs_truncate_rotated.txt b/changes-entries/rotatlogs_truncate_rotated.txt
new file mode 100644
index 0000000000..2cc69366ea
--- /dev/null
+++ b/changes-entries/rotatlogs_truncate_rotated.txt
@@ -0,0 +1,2 @@
+ *) rotatelogs: Add -T flag to allow subsequent rotated logfiles to be
+ truncated without the initial logfile being truncated. [Eric Covener]
diff --git a/docs/manual/programs/rotatelogs.xml b/docs/manual/programs/rotatelogs.xml
index f152721af6..5b31a8af0e 100644
--- a/docs/manual/programs/rotatelogs.xml
+++ b/docs/manual/programs/rotatelogs.xml
@@ -104,6 +104,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. Available in 2.4.56 and later.
+</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
@@ -242,6 +249,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>
diff --git a/support/rotatelogs.c b/support/rotatelogs.c
index 3227b552fa..e0819da548 100644
--- a/support/rotatelogs.c
+++ b/support/rotatelogs.c
@@ -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"
@@ -380,6 +382,8 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
apr_status_t rv;
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);
@@ -459,8 +463,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. */
@@ -474,6 +487,19 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status)
/* New log file is now 'current'. */
status->current = newlog;
+
+ /* The first write to the initial file hasn't checked for size.
+ * In the normalized timestamp case and the custom strftime case with
+ * any reasonable accuracy, it's futile as the rotation will pick the
+ * same filename again.
+ * For -n, when not truncating, check and rotate.
+ */
+ if (config->num_files > 0 && oldreason == ROTATE_NEW && !config->truncate) {
+ checkRotate(config, status);
+ if (status->rotateReason != ROTATE_NONE) {
+ doRotate(config, status);
+ }
+ }
}
else {
char *error = apr_psprintf(newlog.pool, "%pm", &rv);
@@ -585,9 +611,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':
@@ -612,6 +638,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;