2.4.x patch: svn merge -c 1826973 ^/httpd/httpd/trunk .
+1: rjung, ylavic, jim
- *) rotatelogs: Add an option to autocreate directories to rotatelogs.
- PR: 46669
- trunk patch: http://svn.apache.org/r1533810
- http://svn.apache.org/r1533935
- 2.4.x patch: https://home.apache.org/~rjung/patches/httpd-2.4.x-rotatelogs-create-directories-v2.patch
- plus CHANGES for new "-d" flag (see svn log for credits).
- Merge only fails due to small docs conflicts.
- +1: rjung, ylavic, niq
- jung: I'll wait a bit whether the below remaining rotatelogs patch makes it to apply in order.
-
- *) rotatelogs: Choose "-D" instead of "-d" for the rotatelogs
- option that creates the path to the log file.
- I want to use "-d" for another directory related
- option next where (I think) the "directory" "d"
- makes more sense.
- "-d" has not yet been backported, so changing
- to "-D" is not a real compatibility issue.
- This brings 2.4.x rotatelogs in sync with trunk.
- trunk patch: http://svn.apache.org/r1666417
- 2.4.x patch: https://home.apache.org/~rjung/patches/httpd-2.4.x-rotatelogs-create-directories-rename-flag.patch
- plus CHANGES change from "-d" to "-D"
- Merge only fails due to small docs conflicts.
- +1: rjung, ylavic, niq
- jung: I'll wait a bit whether the below remaining rotatelogs patch makes it to apply in order.
-
*) Some easy proposals:
- mod_logio, mod_ssl: Remove pointless static in optional fn pointer
variable declaration
.el .ne 3
.IP "\\$1" \\$2
..
-.TH "ROTATELOGS" 8 "2015-01-01" "Apache HTTP Server" "rotatelogs"
+.TH "ROTATELOGS" 8 "2018-03-15" "Apache HTTP Server" "rotatelogs"
.SH NAME
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 ] [ -\fBt\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 ] [ -\fBt\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"
-f
Causes the logfile to be opened immediately, as soon as rotatelogs starts, instead of waiting for the first logfile entry to be read (for non-busy sites, there may be a substantial delay between when the server is started 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)
.TP
+-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\&.
+.TP
-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, and there is no need for archived data\&. No suffix will be added to the filename, however format strings containing '%' characters will be respected\&.
.TP
int force_open;
int verbose;
int echo;
- const char *szLogRoot;
+ char *szLogRoot;
int truncate;
const char *linkfile;
const char *postrotate_prog;
int create_empty;
#endif
int num_files;
+ int create_path;
};
typedef struct rotate_status rotate_status_t;
}
fprintf(stderr,
#if APR_FILES_AS_SOCKETS
- "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-t] [-e] [-c] [-n number] <logfile> "
+ "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-D] [-t] [-e] [-c] [-n number] <logfile> "
#else
- "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-t] [-e] [-n number] <logfile> "
+ "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-D] [-t] [-e] [-n number] <logfile> "
#endif
"{<rotation time in seconds>|<rotation size>(B|K|M|G)} "
"[offset minutes from UTC]\n\n",
" -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
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");
}
}
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);
}
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':
case 'f':
config.force_open = 1;
break;
+ case 'D':
+ config.create_path = 1;
+ break;
case 't':
config.truncate = 1;
break;
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++) {