From: Ben Reser Date: Sat, 19 Oct 2013 19:10:33 +0000 (+0000) Subject: Add an option to autocreate directories to rotatelogs. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c1f9e12a2c6c643cf8edded47427870ca3ca672;p=thirdparty%2Fapache%2Fhttpd.git Add an option to autocreate directories to rotatelogs. * support/rotatelogs.c (rotate_config): Remove const from szLogRoot since we'll be passing it to apr_filepath_merge. Add create_path member. (usage, dumpConfig): Update to reflect new -d option. (doRotate): Add code that knows how to create the directories a log file is going to go into. (main): Add the -d option and canonicalize the incoming path with apr_filepath_merge() so that the code in doRotate can work properly. * docs/man/rotatelogs.8, docs/manual/programs/rotatelogs.html.en: Update for -d option. PR: 46669 Submitted by: Philippe Lantin (which was actually a patch written by myself when I worked there) Tweaked by: breser (ported to trunk and changed option from -p to -d) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1533810 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/docs/man/rotatelogs.8 b/docs/man/rotatelogs.8 index cbbe5863b23..35693877762 100644 --- a/docs/man/rotatelogs.8 +++ b/docs/man/rotatelogs.8 @@ -19,7 +19,7 @@ .el .ne 3 .IP "\\$1" \\$2 .. -.TH "ROTATELOGS" 8 "2013-06-12" "Apache HTTP Server" "rotatelogs" +.TH "ROTATELOGS" 8 "2013-08-19" "Apache HTTP Server" "rotatelogs" .SH NAME rotatelogs \- Piped logging program to rotate Apache logs @@ -27,7 +27,7 @@ rotatelogs \- Piped logging program to rotate Apache logs .SH "SYNOPSIS" .PP -\fBrotatelogs\fR [ -\fBl\fR ] [ -\fBL\fR \fIlinkname\fR ] [ -\fBp\fR \fIprogram\fR ] [ -\fBf\fR ] [ -\fBv\fR ] [ -\fBe\fR ] [ -\fBc\fR ] [ -\fBn\fR \fInumber-of-files\fR ] \fIlogfile\fR \fIrotationtime\fR|\fIfilesize\fR(B|K|M|G) [ \fIoffset\fR ] +\fBrotatelogs\fR [ -\fBl\fR ] [ -\fBL\fR \fIlinkname\fR ] [ -\fBp\fR \fIprogram\fR ] [ -\fBf\fR ] [ -\fBd\fR ] [ -\fBv\fR ] [ -\fBe\fR ] [ -\fBc\fR ] [ -\fBn\fR \fInumber-of-files\fR ] \fIlogfile\fR \fIrotationtime\fR|\fIfilesize\fR(B|K|M|G) [ \fIoffset\fR ] .SH "SUMMARY" @@ -67,6 +67,9 @@ Create log file for each interval, even if empty\&. -n \fInumber-of-files\fR Use a circular list of filenames without timestamps\&. With -n 3, the series of log files opened would be "logfile", "logfile\&.1", "logfile\&.2", then overwriting "logfile"\&. .TP +-d +Creates the parent directories that the log file will be placed in if they do not already exist\&. This allows strftime(3) formatting to be used in the path and not just the filename\&. +.TP \fIlogfile\fR .PP The path plus basename of the logfile\&. If \fIlogfile\fR includes any '%' characters, it is treated as a format string for strftime(3)\&. Otherwise, the suffix \fI\&.nnnnnnnnnn\fR is automatically added and is the time in seconds (unless the -t option is used)\&. Both formats compute the start time from the beginning of the current period\&. For example, if a rotation time of 86400 is specified, the hour, minute, and second fields created from the strftime(3) format will all be zero, referring to the beginning of the current 24-hour period (midnight)\&. .PP When using strftime(3) filename formatting, be sure the log file format has enough granularity to produce a different file name each time the logs are rotated\&. Otherwise rotation will overwrite the same file instead of starting a new one\&. For example, if \fIlogfile\fR was /var/logs/errorlog\&.%Y-%m-%d with log rotation at 5 megabytes, but 5 megabytes was reached twice in the same day, the same log file name would be produced and log rotation would keep writing to the same file\&. .TP diff --git a/docs/manual/programs/rotatelogs.html.en b/docs/manual/programs/rotatelogs.html.en index 841ed1265da..23e163f3916 100644 --- a/docs/manual/programs/rotatelogs.html.en +++ b/docs/manual/programs/rotatelogs.html.en @@ -44,6 +44,7 @@ [ -L linkname ] [ -p program ] [ -f ] + [ -d ] [ -v ] [ -e ] [ -c ] @@ -89,6 +90,11 @@ and when the first request is handled, meaning that the associated logfile does not "exist" until then, which causes problems from some automated logging tools) +
-d
+
Creates the parent directories of the path that the log file will be +placed in if they do not already exist. This allows strftime(3) +formatting to be used in the path and not just the filename.
+
-t
Causes the logfile to be truncated instead of rotated. This is useful when a log is processed in real time by a command like tail, @@ -277,4 +283,4 @@ if (typeof(prettyPrint) !== 'undefined') { prettyPrint(); } //--> - \ No newline at end of file + diff --git a/support/rotatelogs.c b/support/rotatelogs.c index 7c203e59df4..63869ae34a0 100644 --- a/support/rotatelogs.c +++ b/support/rotatelogs.c @@ -63,7 +63,7 @@ struct rotate_config { int force_open; int verbose; int echo; - const char *szLogRoot; + char *szLogRoot; int truncate; const char *linkfile; const char *postrotate_prog; @@ -71,6 +71,7 @@ struct rotate_config { int create_empty; #endif int num_files; + int create_path; }; typedef struct rotate_status rotate_status_t; @@ -103,9 +104,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] [-t] [-e] [-c] [-n number] " + "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-d] [-t] [-e] [-c] [-n number] " #else - "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-t] [-e] [-n number] " + "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-d] [-t] [-e] [-n number] " #endif "{|(B|K|M|G)} " "[offset minutes from UTC]\n\n", @@ -137,6 +138,7 @@ static void usage(const char *argv0, const char *reason) " -L path Create hard link from current log to specified path.\n" " -p prog Run specified program after opening a new log file. See below.\n" " -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" " -e Echo log to stdout for further processing.\n" #if APR_FILES_AS_SOCKETS @@ -200,6 +202,7 @@ static void dumpConfig (rotate_config_t *config) fprintf(stderr, "Rotation based on localtime: %12s\n", config->use_localtime ? "yes" : "no"); fprintf(stderr, "Rotation file date pattern: %12s\n", config->use_strftime ? "yes" : "no"); fprintf(stderr, "Rotation file forced open: %12s\n", config->force_open ? "yes" : "no"); + fprintf(stderr, "Create parent directories: %12s\n", config->create_path ? "yes" : "no"); fprintf(stderr, "Rotation verbose: %12s\n", config->verbose ? "yes" : "no"); #if APR_FILES_AS_SOCKETS fprintf(stderr, "Rotation create empty logs: %12s\n", config->create_empty ? "yes" : "no"); @@ -430,6 +433,23 @@ static void doRotate(rotate_config_t *config, rotate_status_t *status) } } apr_pool_create(&newlog.pool, status->pool); + if (config->create_path) { + char *ptr = strrchr(newlog.name, '/'); + if (ptr && ptr > newlog.name) { + char *path = apr_pstrmemdup(newlog.pool, newlog.name, ptr - newlog.name); + if (config->verbose) { + fprintf(stderr, "Creating directory tree %s\n", path); + } + rv = apr_dir_make_recursive(path, APR_FPROT_OS_DEFAULT, newlog.pool); + if (rv != APR_SUCCESS) { + char error[120]; + + apr_strerror(rv, error, sizeof error); + fprintf(stderr, "Could not create directory '%s' (%s)\n", path, error); + exit(2); + } + } + } if (config->verbose) { fprintf(stderr, "Opening file %s\n", newlog.name); } @@ -560,9 +580,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:ftvecn:", &c, &opt_arg)) == APR_SUCCESS) { + while ((rv = apr_getopt(opt, "lL:p:fdtvecn:", &c, &opt_arg)) == APR_SUCCESS) { #else - while ((rv = apr_getopt(opt, "lL:p:ftven:", &c, &opt_arg)) == APR_SUCCESS) { + while ((rv = apr_getopt(opt, "lL:p:fdtven:", &c, &opt_arg)) == APR_SUCCESS) { #endif switch (c) { case 'l': @@ -577,6 +597,9 @@ int main (int argc, const char * const argv[]) case 'f': config.force_open = 1; break; + case 'd': + config.create_path = 1; + break; case 't': config.truncate = 1; break; @@ -611,7 +634,11 @@ int main (int argc, const char * const argv[]) usage(argv[0], "Incorrect number of arguments"); } - config.szLogRoot = argv[opt->ind++]; + rv = apr_filepath_merge(&config.szLogRoot, "", argv[opt->ind++], + APR_FILEPATH_TRUENAME, status.pool); + if (rv != APR_SUCCESS && rv != APR_EPATHWILD) { + usage(argv[0], "Invalid filename given"); + } /* Read in the remaining flags, namely time, size and UTC offset. */ for(; opt->ind < argc; opt->ind++) {