aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-08-02 00:55:49 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-08-02 00:55:49 +0200
commitaebb742939d4100fbd1c7e94c68f9265e0805fd8 (patch)
tree0ccb74b0e7746125fab567d1663860c69e9d0b6a
parente2944af43eeb95ec612a48cc930a71f9e6a2f219 (diff)
downloadbusybox-w32-aebb742939d4100fbd1c7e94c68f9265e0805fd8.tar.gz
busybox-w32-aebb742939d4100fbd1c7e94c68f9265e0805fd8.tar.bz2
busybox-w32-aebb742939d4100fbd1c7e94c68f9265e0805fd8.zip
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 <vda.linux@googlemail.com>
-rw-r--r--runit/runit_lib.c2
-rw-r--r--runit/runit_lib.h6
-rw-r--r--runit/runsvdir.c2
-rw-r--r--runit/svlogd.c154
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.
34#include "libbb.h" 34#include "libbb.h"
35#include "runit_lib.h" 35#include "runit_lib.h"
36 36
37#ifdef UNUSED
37unsigned byte_chr(char *s,unsigned n,int c) 38unsigned byte_chr(char *s,unsigned n,int c)
38{ 39{
39 char ch; 40 char ch;
@@ -50,7 +51,6 @@ unsigned byte_chr(char *s,unsigned n,int c)
50 return t - s; 51 return t - s;
51} 52}
52 53
53#ifdef UNUSED
54static /* as it isn't used anywhere else */ 54static /* as it isn't used anywhere else */
55void tai_pack(char *s, const struct tai *t) 55void tai_pack(char *s, const struct tai *t)
56{ 56{
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.
27 27
28PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 28PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
29 29
30extern unsigned byte_chr(char *s,unsigned n,int c); 30//extern unsigned byte_chr(char *s,unsigned n,int c);
31 31//
32#define direntry struct dirent
33
34//struct tai { 32//struct tai {
35// uint64_t x; 33// uint64_t x;
36//}; 34//};
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)
129static NOINLINE int do_rescan(void) 129static NOINLINE int do_rescan(void)
130{ 130{
131 DIR *dir; 131 DIR *dir;
132 direntry *d; 132 struct dirent *d;
133 int i; 133 int i;
134 struct stat s; 134 struct stat s;
135 int need_rescan = 0; 135 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.
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29/* TODO: depends on runit_lib.c - review and reduce/eliminate */ 29/* TODO: depends on runit_lib.c - review and reduce/eliminate */
30 30
31/*
32Config files
33
34On startup, and after receiving a HUP signal, svlogd checks for each
35log directory log if the configuration file log/config exists,
36and if so, reads the file line by line and adjusts configuration
37for log as follows:
38
39If the line is empty, or starts with a #, it is ignored. A line
40of the form
41
42ssize
43 sets the maximum file size of current when svlogd should rotate
44 the current log file to size bytes. Default is 1000000.
45 If size is zero, svlogd doesnt rotate log files
46 You should set size to at least (2 * len).
47nnum
48 sets the number of old log files svlogd should maintain to num.
49 If svlogd sees more that num old log files in log after log file
50 rotation, it deletes the oldest one. Default is 10.
51 If num is zero, svlogd doesnt remove old log files.
52Nmin
53 sets the minimum number of old log files svlogd should maintain
54 to min. min must be less than num. If min is set, and svlogd
55 cannot write to current because the filesystem is full,
56 and it sees more than min old log files, it deletes the oldest one.
57ttimeout
58 sets the maximum age of the current log file when svlogd should
59 rotate the current log file to timeout seconds. If current
60 is timeout seconds old, and is not empty, svlogd forces log file rotation.
61!processor
62 tells svlogd to feed each recent log file through processor
63 (see above) on log file rotation. By default log files are not processed.
64ua.b.c.d[:port]
65 tells svlogd to transmit the first len characters of selected
66 log messages to the IP address a.b.c.d, port number port.
67 If port isnt set, the default port for syslog is used (514).
68 len can be set through the -l option, see below. If svlogd
69 has trouble sending udp packets, it writes error messages
70 to the log directory. Attention: logging through udp is unreliable,
71 and should be used in private networks only.
72Ua.b.c.d[:port]
73 is the same as the u line above, but the log messages are no longer
74 written to the log directory, but transmitted through udp only.
75 Error messages from svlogd concerning sending udp packages still go
76 to the log directory.
77pprefix
78 tells svlogd to prefix each line to be written to the log directory,
79 to standard error, or through UDP, with prefix.
80
81If a line starts with a -, +, e, or E, svlogd matches the first len characters
82of each log message against pattern and acts accordingly:
83
84-pattern
85 the log message is deselected.
86+pattern
87 the log message is selected.
88epattern
89 the log message is selected to be printed to standard error.
90Epattern
91 the log message is deselected to be printed to standard error.
92
93Initially each line is selected to be written to log/current. Deselected
94log messages are discarded from log. Initially each line is deselected
95to be written to standard err. Log messages selected for standard error
96are written to standard error.
97
98Pattern Matching
99
100svlogd matches a log message against the string pattern as follows:
101
102pattern is applied to the log message one character by one, starting
103with the first. A character not a star (*) and not a plus (+) matches itself.
104A plus matches the next character in pattern in the log message one
105or more times. A star before the end of pattern matches any string
106in the log message that does not include the next character in pattern.
107A star at the end of pattern matches any string.
108
109Timestamps optionally added by svlogd are not considered part
110of the log message.
111
112An svlogd pattern is not a regular expression. For example consider
113a log message like this
114
1152005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14
116
117The following pattern doesnt match
118
119-*pid*
120
121because the first star matches up to the first p in tcpsvd,
122and then the match fails because i is not s. To match this
123log message, you can use a pattern like this instead
124
125-*: *: pid *
126*/
127
31#include <sys/poll.h> 128#include <sys/poll.h>
32#include <sys/file.h> 129#include <sys/file.h>
33#include "libbb.h" 130#include "libbb.h"
@@ -72,6 +169,8 @@ struct globals {
72 int wstat; 169 int wstat;
73 unsigned nearest_rotate; 170 unsigned nearest_rotate;
74 171
172 void* (*memRchr)(const void *, int, size_t);
173
75 smallint exitasap; 174 smallint exitasap;
76 smallint rotateasap; 175 smallint rotateasap;
77 smallint reopenasap; 176 smallint reopenasap;
@@ -94,6 +193,7 @@ struct globals {
94#define fndir (G.fndir ) 193#define fndir (G.fndir )
95#define fdwdir (G.fdwdir ) 194#define fdwdir (G.fdwdir )
96#define wstat (G.wstat ) 195#define wstat (G.wstat )
196#define memRchr (G.memRchr )
97#define nearest_rotate (G.nearest_rotate) 197#define nearest_rotate (G.nearest_rotate)
98#define exitasap (G.exitasap ) 198#define exitasap (G.exitasap )
99#define rotateasap (G.rotateasap ) 199#define rotateasap (G.rotateasap )
@@ -121,7 +221,6 @@ struct globals {
121#define PAUSE "pausing: " 221#define PAUSE "pausing: "
122#define INFO "info: " 222#define INFO "info: "
123 223
124#define usage() bb_show_usage()
125static void fatalx(const char *m0) 224static void fatalx(const char *m0)
126{ 225{
127 bb_error_msg_and_die(FATAL"%s", m0); 226 bb_error_msg_and_die(FATAL"%s", m0);
@@ -273,7 +372,8 @@ static unsigned processorstop(struct logdir *ld)
273 sig_block(SIGHUP); 372 sig_block(SIGHUP);
274 ld->ppid = 0; 373 ld->ppid = 0;
275 } 374 }
276 if (ld->fddir == -1) return 1; 375 if (ld->fddir == -1)
376 return 1;
277 while (fchdir(ld->fddir) == -1) 377 while (fchdir(ld->fddir) == -1)
278 pause2cannot("change directory, want processor", ld->name); 378 pause2cannot("change directory, want processor", ld->name);
279 if (WEXITSTATUS(wstat) != 0) { 379 if (WEXITSTATUS(wstat) != 0) {
@@ -564,6 +664,10 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
564 case '-': 664 case '-':
565 case 'e': 665 case 'e':
566 case 'E': 666 case 'E':
667 /* Filtering requires one-line buffering,
668 * resetting the "find newline" function
669 * accordingly */
670 memRchr = memchr;
567 /* Add '\n'-terminated line to ld->inst */ 671 /* Add '\n'-terminated line to ld->inst */
568 while (1) { 672 while (1) {
569 int l = asprintf(&new, "%s%s\n", ld->inst ? : "", s); 673 int l = asprintf(&new, "%s%s\n", ld->inst ? : "", s);
@@ -708,7 +812,7 @@ static int buffer_pread(/*int fd, */char *s, unsigned len)
708 struct pollfd input; 812 struct pollfd input;
709 int i; 813 int i;
710 814
711 input.fd = 0; 815 input.fd = STDIN_FILENO;
712 input.events = POLLIN; 816 input.events = POLLIN;
713 817
714 do { 818 do {
@@ -852,12 +956,11 @@ static void logmatch(struct logdir *ld)
852int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 956int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
853int svlogd_main(int argc, char **argv) 957int svlogd_main(int argc, char **argv)
854{ 958{
855 char *r,*l,*b; 959 char *r, *l, *b;
856 ssize_t stdin_cnt = 0; 960 ssize_t stdin_cnt = 0;
857 int i; 961 int i;
858 unsigned opt; 962 unsigned opt;
859 unsigned timestamp = 0; 963 unsigned timestamp = 0;
860 void* (*memRchr)(const void *, int, size_t) = memchr;
861 964
862 INIT_G(); 965 INIT_G();
863 966
@@ -866,13 +969,16 @@ int svlogd_main(int argc, char **argv)
866 &r, &replace, &l, &b, &timestamp, &verbose); 969 &r, &replace, &l, &b, &timestamp, &verbose);
867 if (opt & 1) { // -r 970 if (opt & 1) { // -r
868 repl = r[0]; 971 repl = r[0];
869 if (!repl || r[1]) usage(); 972 if (!repl || r[1])
973 bb_show_usage();
870 } 974 }
871 if (opt & 2) if (!repl) repl = '_'; // -R 975 if (opt & 2) if (!repl) repl = '_'; // -R
872 if (opt & 4) { // -l 976 if (opt & 4) { // -l
873 linemax = xatou_range(l, 0, BUFSIZ-26); 977 linemax = xatou_range(l, 0, BUFSIZ-26);
874 if (linemax == 0) linemax = BUFSIZ-26; 978 if (linemax == 0)
875 if (linemax < 256) linemax = 256; 979 linemax = BUFSIZ-26;
980 if (linemax < 256)
981 linemax = 256;
876 } 982 }
877 ////if (opt & 8) { // -b 983 ////if (opt & 8) { // -b
878 //// buflen = xatoi_u(b); 984 //// buflen = xatoi_u(b);
@@ -885,11 +991,12 @@ int svlogd_main(int argc, char **argv)
885 argc -= optind; 991 argc -= optind;
886 992
887 dirn = argc; 993 dirn = argc;
888 if (dirn <= 0) usage(); 994 if (dirn <= 0)
889 ////if (buflen <= linemax) usage(); 995 bb_show_usage();
996 ////if (buflen <= linemax) bb_show_usage();
890 fdwdir = xopen(".", O_RDONLY|O_NDELAY); 997 fdwdir = xopen(".", O_RDONLY|O_NDELAY);
891 close_on_exec_on(fdwdir); 998 close_on_exec_on(fdwdir);
892 dir = xzalloc(dirn * sizeof(struct logdir)); 999 dir = xzalloc(dirn * sizeof(dir[0]));
893 for (i = 0; i < dirn; ++i) { 1000 for (i = 0; i < dirn; ++i) {
894 dir[i].fddir = -1; 1001 dir[i].fddir = -1;
895 dir[i].fdcur = -1; 1002 dir[i].fdcur = -1;
@@ -914,13 +1021,14 @@ int svlogd_main(int argc, char **argv)
914 bb_signals_recursive_norestart(1 << SIGALRM, sig_alarm_handler); 1021 bb_signals_recursive_norestart(1 << SIGALRM, sig_alarm_handler);
915 bb_signals_recursive_norestart(1 << SIGHUP, sig_hangup_handler); 1022 bb_signals_recursive_norestart(1 << SIGHUP, sig_hangup_handler);
916 1023
917 logdirs_reopen();
918
919 /* Without timestamps, we don't have to print each line 1024 /* Without timestamps, we don't have to print each line
920 * separately, so we can look for _last_ newline, not first, 1025 * separately, so we can look for _last_ newline, not first,
921 * thus batching writes */ 1026 * thus batching writes. If filtering is enabled in config,
922 if (!timestamp) 1027 * logdirs_reopen resets it to memchr.
923 memRchr = memrchr; 1028 */
1029 memRchr = (timestamp ? memchr : memrchr);
1030
1031 logdirs_reopen();
924 1032
925 setvbuf(stderr, NULL, _IOFBF, linelen); 1033 setvbuf(stderr, NULL, _IOFBF, linelen);
926 1034
@@ -988,7 +1096,8 @@ int svlogd_main(int argc, char **argv)
988 } 1096 }
989 for (i = 0; i < dirn; ++i) { 1097 for (i = 0; i < dirn; ++i) {
990 struct logdir *ld = &dir[i]; 1098 struct logdir *ld = &dir[i];
991 if (ld->fddir == -1) continue; 1099 if (ld->fddir == -1)
1100 continue;
992 if (ld->inst) 1101 if (ld->inst)
993 logmatch(ld); 1102 logmatch(ld);
994 if (ld->matcherr == 'e') { 1103 if (ld->matcherr == 'e') {
@@ -996,7 +1105,8 @@ int svlogd_main(int argc, char **argv)
996 ////full_write(STDERR_FILENO, printptr, printlen); 1105 ////full_write(STDERR_FILENO, printptr, printlen);
997 fwrite(printptr, 1, printlen, stderr); 1106 fwrite(printptr, 1, printlen, stderr);
998 } 1107 }
999 if (ld->match != '+') continue; 1108 if (ld->match != '+')
1109 continue;
1000 buffer_pwrite(i, printptr, printlen); 1110 buffer_pwrite(i, printptr, printlen);
1001 } 1111 }
1002 1112
@@ -1019,12 +1129,14 @@ int svlogd_main(int argc, char **argv)
1019 } 1129 }
1020 /* linelen == no of chars incl. '\n' (or == stdin_cnt) */ 1130 /* linelen == no of chars incl. '\n' (or == stdin_cnt) */
1021 for (i = 0; i < dirn; ++i) { 1131 for (i = 0; i < dirn; ++i) {
1022 if (dir[i].fddir == -1) continue; 1132 if (dir[i].fddir == -1)
1133 continue;
1023 if (dir[i].matcherr == 'e') { 1134 if (dir[i].matcherr == 'e') {
1024 ////full_write(STDERR_FILENO, lineptr, linelen); 1135 ////full_write(STDERR_FILENO, lineptr, linelen);
1025 fwrite(lineptr, 1, linelen, stderr); 1136 fwrite(lineptr, 1, linelen, stderr);
1026 } 1137 }
1027 if (dir[i].match != '+') continue; 1138 if (dir[i].match != '+')
1139 continue;
1028 buffer_pwrite(i, lineptr, linelen); 1140 buffer_pwrite(i, lineptr, linelen);
1029 } 1141 }
1030 } 1142 }
@@ -1046,7 +1158,7 @@ int svlogd_main(int argc, char **argv)
1046 for (i = 0; i < dirn; ++i) { 1158 for (i = 0; i < dirn; ++i) {
1047 if (dir[i].ppid) 1159 if (dir[i].ppid)
1048 while (!processorstop(&dir[i])) 1160 while (!processorstop(&dir[i]))
1049 /* repeat */; 1161 continue;
1050 logdir_close(&dir[i]); 1162 logdir_close(&dir[i]);
1051 } 1163 }
1052 return 0; 1164 return 0;