From aebb742939d4100fbd1c7e94c68f9265e0805fd8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Aug 2009 00:55:49 +0200 Subject: [PATCH] svlogd: fix bug 521: use line buffering if any filtering is done function old new delta logdirs_reopen 1296 1310 +14 svlogd_main 1439 1444 +5 Signed-off-by: Denys Vlasenko --- runit/runit_lib.c | 2 +- runit/runit_lib.h | 6 +- runit/runsvdir.c | 2 +- runit/svlogd.c | 154 +++++++++++++++++++++++++++++++++++++++------- 4 files changed, 137 insertions(+), 27 deletions(-) diff --git a/runit/runit_lib.c b/runit/runit_lib.c index f33619d28..ec18b5edd 100644 --- a/runit/runit_lib.c +++ b/runit/runit_lib.c @@ -34,6 +34,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "libbb.h" #include "runit_lib.h" +#ifdef UNUSED unsigned byte_chr(char *s,unsigned n,int c) { char ch; @@ -50,7 +51,6 @@ unsigned byte_chr(char *s,unsigned n,int c) return t - s; } -#ifdef UNUSED static /* as it isn't used anywhere else */ void tai_pack(char *s, const struct tai *t) { diff --git a/runit/runit_lib.h b/runit/runit_lib.h index 28769e5fa..88d1c9f22 100644 --- a/runit/runit_lib.h +++ b/runit/runit_lib.h @@ -27,10 +27,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN -extern unsigned byte_chr(char *s,unsigned n,int c); - -#define direntry struct dirent - +//extern unsigned byte_chr(char *s,unsigned n,int c); +// //struct tai { // uint64_t x; //}; diff --git a/runit/runsvdir.c b/runit/runsvdir.c index a77bc3fd8..492c2a57b 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -129,7 +129,7 @@ static NOINLINE pid_t runsv(const char *name) static NOINLINE int do_rescan(void) { DIR *dir; - direntry *d; + struct dirent *d; int i; struct stat s; int need_rescan = 0; diff --git a/runit/svlogd.c b/runit/svlogd.c index 79286a3ee..25c169aeb 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -28,6 +28,103 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ /* TODO: depends on runit_lib.c - review and reduce/eliminate */ +/* +Config files + +On startup, and after receiving a HUP signal, svlogd checks for each +log directory log if the configuration file log/config exists, +and if so, reads the file line by line and adjusts configuration +for log as follows: + +If the line is empty, or starts with a #, it is ignored. A line +of the form + +ssize + sets the maximum file size of current when svlogd should rotate + the current log file to size bytes. Default is 1000000. + If size is zero, svlogd doesnt rotate log files + You should set size to at least (2 * len). +nnum + sets the number of old log files svlogd should maintain to num. + If svlogd sees more that num old log files in log after log file + rotation, it deletes the oldest one. Default is 10. + If num is zero, svlogd doesnt remove old log files. +Nmin + sets the minimum number of old log files svlogd should maintain + to min. min must be less than num. If min is set, and svlogd + cannot write to current because the filesystem is full, + and it sees more than min old log files, it deletes the oldest one. +ttimeout + sets the maximum age of the current log file when svlogd should + rotate the current log file to timeout seconds. If current + is timeout seconds old, and is not empty, svlogd forces log file rotation. +!processor + tells svlogd to feed each recent log file through processor + (see above) on log file rotation. By default log files are not processed. +ua.b.c.d[:port] + tells svlogd to transmit the first len characters of selected + log messages to the IP address a.b.c.d, port number port. + If port isnt set, the default port for syslog is used (514). + len can be set through the -l option, see below. If svlogd + has trouble sending udp packets, it writes error messages + to the log directory. Attention: logging through udp is unreliable, + and should be used in private networks only. +Ua.b.c.d[:port] + is the same as the u line above, but the log messages are no longer + written to the log directory, but transmitted through udp only. + Error messages from svlogd concerning sending udp packages still go + to the log directory. +pprefix + tells svlogd to prefix each line to be written to the log directory, + to standard error, or through UDP, with prefix. + +If a line starts with a -, +, e, or E, svlogd matches the first len characters +of each log message against pattern and acts accordingly: + +-pattern + the log message is deselected. ++pattern + the log message is selected. +epattern + the log message is selected to be printed to standard error. +Epattern + the log message is deselected to be printed to standard error. + +Initially each line is selected to be written to log/current. Deselected +log messages are discarded from log. Initially each line is deselected +to be written to standard err. Log messages selected for standard error +are written to standard error. + +Pattern Matching + +svlogd matches a log message against the string pattern as follows: + +pattern is applied to the log message one character by one, starting +with the first. A character not a star (*) and not a plus (+) matches itself. +A plus matches the next character in pattern in the log message one +or more times. A star before the end of pattern matches any string +in the log message that does not include the next character in pattern. +A star at the end of pattern matches any string. + +Timestamps optionally added by svlogd are not considered part +of the log message. + +An svlogd pattern is not a regular expression. For example consider +a log message like this + +2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14 + +The following pattern doesnt match + +-*pid* + +because the first star matches up to the first p in tcpsvd, +and then the match fails because i is not s. To match this +log message, you can use a pattern like this instead + +-*: *: pid * +*/ + #include #include #include "libbb.h" @@ -72,6 +169,8 @@ struct globals { int wstat; unsigned nearest_rotate; + void* (*memRchr)(const void *, int, size_t); + smallint exitasap; smallint rotateasap; smallint reopenasap; @@ -94,6 +193,7 @@ struct globals { #define fndir (G.fndir ) #define fdwdir (G.fdwdir ) #define wstat (G.wstat ) +#define memRchr (G.memRchr ) #define nearest_rotate (G.nearest_rotate) #define exitasap (G.exitasap ) #define rotateasap (G.rotateasap ) @@ -121,7 +221,6 @@ struct globals { #define PAUSE "pausing: " #define INFO "info: " -#define usage() bb_show_usage() static void fatalx(const char *m0) { bb_error_msg_and_die(FATAL"%s", m0); @@ -273,7 +372,8 @@ static unsigned processorstop(struct logdir *ld) sig_block(SIGHUP); ld->ppid = 0; } - if (ld->fddir == -1) return 1; + if (ld->fddir == -1) + return 1; while (fchdir(ld->fddir) == -1) pause2cannot("change directory, want processor", ld->name); if (WEXITSTATUS(wstat) != 0) { @@ -564,6 +664,10 @@ static unsigned logdir_open(struct logdir *ld, const char *fn) case '-': case 'e': case 'E': + /* Filtering requires one-line buffering, + * resetting the "find newline" function + * accordingly */ + memRchr = memchr; /* Add '\n'-terminated line to ld->inst */ while (1) { int l = asprintf(&new, "%s%s\n", ld->inst ? : "", s); @@ -708,7 +812,7 @@ static int buffer_pread(/*int fd, */char *s, unsigned len) struct pollfd input; int i; - input.fd = 0; + input.fd = STDIN_FILENO; input.events = POLLIN; do { @@ -852,12 +956,11 @@ static void logmatch(struct logdir *ld) int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int svlogd_main(int argc, char **argv) { - char *r,*l,*b; + char *r, *l, *b; ssize_t stdin_cnt = 0; int i; unsigned opt; unsigned timestamp = 0; - void* (*memRchr)(const void *, int, size_t) = memchr; INIT_G(); @@ -866,13 +969,16 @@ int svlogd_main(int argc, char **argv) &r, &replace, &l, &b, ×tamp, &verbose); if (opt & 1) { // -r repl = r[0]; - if (!repl || r[1]) usage(); + if (!repl || r[1]) + bb_show_usage(); } if (opt & 2) if (!repl) repl = '_'; // -R if (opt & 4) { // -l linemax = xatou_range(l, 0, BUFSIZ-26); - if (linemax == 0) linemax = BUFSIZ-26; - if (linemax < 256) linemax = 256; + if (linemax == 0) + linemax = BUFSIZ-26; + if (linemax < 256) + linemax = 256; } ////if (opt & 8) { // -b //// buflen = xatoi_u(b); @@ -885,11 +991,12 @@ int svlogd_main(int argc, char **argv) argc -= optind; dirn = argc; - if (dirn <= 0) usage(); - ////if (buflen <= linemax) usage(); + if (dirn <= 0) + bb_show_usage(); + ////if (buflen <= linemax) bb_show_usage(); fdwdir = xopen(".", O_RDONLY|O_NDELAY); close_on_exec_on(fdwdir); - dir = xzalloc(dirn * sizeof(struct logdir)); + dir = xzalloc(dirn * sizeof(dir[0])); for (i = 0; i < dirn; ++i) { dir[i].fddir = -1; dir[i].fdcur = -1; @@ -914,13 +1021,14 @@ int svlogd_main(int argc, char **argv) bb_signals_recursive_norestart(1 << SIGALRM, sig_alarm_handler); bb_signals_recursive_norestart(1 << SIGHUP, sig_hangup_handler); - logdirs_reopen(); - /* Without timestamps, we don't have to print each line * separately, so we can look for _last_ newline, not first, - * thus batching writes */ - if (!timestamp) - memRchr = memrchr; + * thus batching writes. If filtering is enabled in config, + * logdirs_reopen resets it to memchr. + */ + memRchr = (timestamp ? memchr : memrchr); + + logdirs_reopen(); setvbuf(stderr, NULL, _IOFBF, linelen); @@ -988,7 +1096,8 @@ int svlogd_main(int argc, char **argv) } for (i = 0; i < dirn; ++i) { struct logdir *ld = &dir[i]; - if (ld->fddir == -1) continue; + if (ld->fddir == -1) + continue; if (ld->inst) logmatch(ld); if (ld->matcherr == 'e') { @@ -996,7 +1105,8 @@ int svlogd_main(int argc, char **argv) ////full_write(STDERR_FILENO, printptr, printlen); fwrite(printptr, 1, printlen, stderr); } - if (ld->match != '+') continue; + if (ld->match != '+') + continue; buffer_pwrite(i, printptr, printlen); } @@ -1019,12 +1129,14 @@ int svlogd_main(int argc, char **argv) } /* linelen == no of chars incl. '\n' (or == stdin_cnt) */ for (i = 0; i < dirn; ++i) { - if (dir[i].fddir == -1) continue; + if (dir[i].fddir == -1) + continue; if (dir[i].matcherr == 'e') { ////full_write(STDERR_FILENO, lineptr, linelen); fwrite(lineptr, 1, linelen, stderr); } - if (dir[i].match != '+') continue; + if (dir[i].match != '+') + continue; buffer_pwrite(i, lineptr, linelen); } } @@ -1046,7 +1158,7 @@ int svlogd_main(int argc, char **argv) for (i = 0; i < dirn; ++i) { if (dir[i].ppid) while (!processorstop(&dir[i])) - /* repeat */; + continue; logdir_close(&dir[i]); } return 0;