diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-02 00:55:49 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-02 00:55:49 +0200 |
commit | aebb742939d4100fbd1c7e94c68f9265e0805fd8 (patch) | |
tree | 0ccb74b0e7746125fab567d1663860c69e9d0b6a | |
parent | e2944af43eeb95ec612a48cc930a71f9e6a2f219 (diff) | |
download | busybox-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.c | 2 | ||||
-rw-r--r-- | runit/runit_lib.h | 6 | ||||
-rw-r--r-- | runit/runsvdir.c | 2 | ||||
-rw-r--r-- | 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. | |||
34 | #include "libbb.h" | 34 | #include "libbb.h" |
35 | #include "runit_lib.h" | 35 | #include "runit_lib.h" |
36 | 36 | ||
37 | #ifdef UNUSED | ||
37 | unsigned byte_chr(char *s,unsigned n,int c) | 38 | unsigned 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 | ||
54 | static /* as it isn't used anywhere else */ | 54 | static /* as it isn't used anywhere else */ |
55 | void tai_pack(char *s, const struct tai *t) | 55 | void 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 | ||
28 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 28 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
29 | 29 | ||
30 | extern 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) | |||
129 | static NOINLINE int do_rescan(void) | 129 | static 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 | /* | ||
32 | Config files | ||
33 | |||
34 | On startup, and after receiving a HUP signal, svlogd checks for each | ||
35 | log directory log if the configuration file log/config exists, | ||
36 | and if so, reads the file line by line and adjusts configuration | ||
37 | for log as follows: | ||
38 | |||
39 | If the line is empty, or starts with a #, it is ignored. A line | ||
40 | of the form | ||
41 | |||
42 | ssize | ||
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). | ||
47 | nnum | ||
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. | ||
52 | Nmin | ||
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. | ||
57 | ttimeout | ||
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. | ||
64 | ua.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. | ||
72 | Ua.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. | ||
77 | pprefix | ||
78 | tells svlogd to prefix each line to be written to the log directory, | ||
79 | to standard error, or through UDP, with prefix. | ||
80 | |||
81 | If a line starts with a -, +, e, or E, svlogd matches the first len characters | ||
82 | of 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. | ||
88 | epattern | ||
89 | the log message is selected to be printed to standard error. | ||
90 | Epattern | ||
91 | the log message is deselected to be printed to standard error. | ||
92 | |||
93 | Initially each line is selected to be written to log/current. Deselected | ||
94 | log messages are discarded from log. Initially each line is deselected | ||
95 | to be written to standard err. Log messages selected for standard error | ||
96 | are written to standard error. | ||
97 | |||
98 | Pattern Matching | ||
99 | |||
100 | svlogd matches a log message against the string pattern as follows: | ||
101 | |||
102 | pattern is applied to the log message one character by one, starting | ||
103 | with the first. A character not a star (*) and not a plus (+) matches itself. | ||
104 | A plus matches the next character in pattern in the log message one | ||
105 | or more times. A star before the end of pattern matches any string | ||
106 | in the log message that does not include the next character in pattern. | ||
107 | A star at the end of pattern matches any string. | ||
108 | |||
109 | Timestamps optionally added by svlogd are not considered part | ||
110 | of the log message. | ||
111 | |||
112 | An svlogd pattern is not a regular expression. For example consider | ||
113 | a log message like this | ||
114 | |||
115 | 2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14 | ||
116 | |||
117 | The following pattern doesnt match | ||
118 | |||
119 | -*pid* | ||
120 | |||
121 | because the first star matches up to the first p in tcpsvd, | ||
122 | and then the match fails because i is not s. To match this | ||
123 | log 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() | ||
125 | static void fatalx(const char *m0) | 224 | static 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) | |||
852 | int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 956 | int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
853 | int svlogd_main(int argc, char **argv) | 957 | int 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, ×tamp, &verbose); | 969 | &r, &replace, &l, &b, ×tamp, &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; |