diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-08-13 03:21:44 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-08-13 03:21:44 +0300 |
commit | 710c8ef7fc69e47c3ab403bc8c59b22994fb9c43 (patch) | |
tree | 3fcfd32bb8e9c7da9d2a89ae040019cbe3f495d2 | |
parent | fa83f20f6308e5d0c6344ade276b63d28f6e78ee (diff) | |
download | tallyman-710c8ef7fc69e47c3ab403bc8c59b22994fb9c43.tar.gz tallyman-710c8ef7fc69e47c3ab403bc8c59b22994fb9c43.tar.bz2 |
tallyman: preserve command's stdout and stderr
* src/tallyman.c: Proxy command's stdout and stderr by default.
Use single -q option to suppress proxying stdout. Use two -q
options to suppress both stdout and stderr (prior behavior).
* src/tallyman.1: Document new behavior
-rw-r--r-- | src/tallyman.1 | 13 | ||||
-rw-r--r-- | src/tallyman.c | 33 |
2 files changed, 39 insertions, 7 deletions
diff --git a/src/tallyman.1 b/src/tallyman.1 index 90a1baa..9cdbaaa 100644 --- a/src/tallyman.1 +++ b/src/tallyman.1 | |||
@@ -1,11 +1,11 @@ | |||
1 | .TH TALLYMAN 1 "July 18, 2018" "TALLYMAN" "Tallyman User Reference" | 1 | .TH TALLYMAN 1 "August 13, 2019" "TALLYMAN" "Tallyman User Reference" |
2 | .SH NAME | 2 | .SH NAME |
3 | tallyman \- health state collector for docker containers | 3 | tallyman \- health state collector for docker containers |
4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
5 | .na | 5 | .na |
6 | .nh | 6 | .nh |
7 | \fBtallyman\fR\ | 7 | \fBtallyman\fR\ |
8 | [\fB\-d\fR]\ | 8 | [\fB\-dq\fR]\ |
9 | [\fB\-h\fR \fINAME\fR]\ | 9 | [\fB\-h\fR \fINAME\fR]\ |
10 | [\fB\-s\fR \fIHOST:PORT\fR]\ | 10 | [\fB\-s\fR \fIHOST:PORT\fR]\ |
11 | [\fB\-v\fR \fIJSON\fR]\ | 11 | [\fB\-v\fR \fIJSON\fR]\ |
@@ -13,6 +13,7 @@ tallyman \- health state collector for docker containers | |||
13 | [\fB\-\-debug\fR]\ | 13 | [\fB\-\-debug\fR]\ |
14 | [\fB\-\-execution\-timeout=\fISECONDS\fR]\ | 14 | [\fB\-\-execution\-timeout=\fISECONDS\fR]\ |
15 | [\fB\-\-hostname=\fINAME\fR]\ | 15 | [\fB\-\-hostname=\fINAME\fR]\ |
16 | [\fB\-\-quiet\fR]\ | ||
16 | [\fB\-\-server=\fIHOST:PORT\fR]\ | 17 | [\fB\-\-server=\fIHOST:PORT\fR]\ |
17 | [\fB\-\-value=\fIJSON\fR]\ | 18 | [\fB\-\-value=\fIJSON\fR]\ |
18 | \fISRVID\fR\ | 19 | \fISRVID\fR\ |
@@ -49,6 +50,12 @@ Increase debug verbosity. | |||
49 | \fB\-h\fR, \fB\-\-hostname=\fINAME\fR | 50 | \fB\-h\fR, \fB\-\-hostname=\fINAME\fR |
50 | Set this server hostname. By default it is determined automatically. | 51 | Set this server hostname. By default it is determined automatically. |
51 | .TP | 52 | .TP |
53 | \fB\-q\fR, \fB\-\-quiet\fR | ||
54 | By default, \fBtallyman\fR would transparently pass \fICOMMAND\fR's | ||
55 | stdout and stderr to the corresponding streams. Single \fB\-q\fR | ||
56 | option suppresses reproducing the stdout. Two \fB\-q\fR options | ||
57 | suppress both stdout and stderr. | ||
58 | .TP | ||
52 | \fB\-s\fR, \fB\-\-server=\fIHOST:PORT\fR | 59 | \fB\-s\fR, \fB\-\-server=\fIHOST:PORT\fR |
53 | Address and port of the data collector. Default is \fIGW\fR:8990, | 60 | Address and port of the data collector. Default is \fIGW\fR:8990, |
54 | where \fIGW\fR is the default gateway of the container. | 61 | where \fIGW\fR is the default gateway of the container. |
@@ -74,7 +81,7 @@ Sergey Poznyakoff | |||
74 | .SH "BUG REPORTS" | 81 | .SH "BUG REPORTS" |
75 | Report bugs to <gray@gnu.org>. | 82 | Report bugs to <gray@gnu.org>. |
76 | .SH COPYRIGHT | 83 | .SH COPYRIGHT |
77 | Copyright \(co 2018 Sergey Poznyakoff | 84 | Copyright \(co 2018\-2019 Sergey Poznyakoff |
78 | .br | 85 | .br |
79 | .na | 86 | .na |
80 | License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> | 87 | License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> |
diff --git a/src/tallyman.c b/src/tallyman.c index f6b095d..fad97b8 100644 --- a/src/tallyman.c +++ b/src/tallyman.c | |||
@@ -40,7 +40,7 @@ struct option longopts[] = { | |||
40 | { "version", no_argument, 0, 'V' }, | 40 | { "version", no_argument, 0, 'V' }, |
41 | { NULL } | 41 | { NULL } |
42 | }; | 42 | }; |
43 | static char shortopts[] = "+?ds:h:v:V"; | 43 | static char shortopts[] = "+?ds:h:qv:V"; |
44 | 44 | ||
45 | void | 45 | void |
46 | help(void) | 46 | help(void) |
@@ -50,6 +50,9 @@ help(void) | |||
50 | printf("OPTIONS are:\n\n"); | 50 | printf("OPTIONS are:\n\n"); |
51 | printf(" -d, --debug increase debug verbosity\n"); | 51 | printf(" -d, --debug increase debug verbosity\n"); |
52 | printf(" -h, --hostname=NAME set this server hostname\n"); | 52 | printf(" -h, --hostname=NAME set this server hostname\n"); |
53 | printf(" -q, --quiet don't display COMMAND's stderr;\n"); | ||
54 | printf(" when used twice, don't display COMMAND's\n"); | ||
55 | printf(" stdout either\n"); | ||
53 | printf(" -s, --server=HOST:PORT remote host server\n"); | 56 | printf(" -s, --server=HOST:PORT remote host server\n"); |
54 | printf(" -v, --value=JSON add JSON object to the report\n"); | 57 | printf(" -v, --value=JSON add JSON object to the report\n"); |
55 | printf(" --connection-timeout=SECONDS\n"); | 58 | printf(" --connection-timeout=SECONDS\n"); |
@@ -175,6 +178,18 @@ sig_alarm(int sig) | |||
175 | longjmp(jmpbuf, 1); | 178 | longjmp(jmpbuf, 1); |
176 | } | 179 | } |
177 | 180 | ||
181 | static void | ||
182 | stdout_linemon(const char *bufptr, size_t bufsize, void *closure) | ||
183 | { | ||
184 | fwrite(bufptr, bufsize, 1, stdout); | ||
185 | } | ||
186 | |||
187 | static void | ||
188 | stderr_linemon(const char *bufptr, size_t bufsize, void *closure) | ||
189 | { | ||
190 | fwrite(bufptr, bufsize, 1, stderr); | ||
191 | } | ||
192 | |||
178 | int | 193 | int |
179 | main(int argc, char **argv) | 194 | main(int argc, char **argv) |
180 | { | 195 | { |
@@ -189,6 +204,7 @@ main(int argc, char **argv) | |||
189 | struct runcap rc; | 204 | struct runcap rc; |
190 | struct shttp_connection *shttp; | 205 | struct shttp_connection *shttp; |
191 | int status; | 206 | int status; |
207 | int rcflags = RCF_TIMEOUT|RCF_STDOUT_LINEMON|RCF_STDERR_LINEMON; | ||
192 | 208 | ||
193 | setprogname(argv[0]); | 209 | setprogname(argv[0]); |
194 | while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) | 210 | while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) |
@@ -212,6 +228,12 @@ main(int argc, char **argv) | |||
212 | case 'V': | 228 | case 'V': |
213 | version(); | 229 | version(); |
214 | exit(0); | 230 | exit(0); |
231 | case 'q': | ||
232 | if (rcflags & RCF_STDOUT_LINEMON) | ||
233 | rcflags &= ~RCF_STDOUT_LINEMON; | ||
234 | else | ||
235 | rcflags &= ~RCF_STDERR_LINEMON; | ||
236 | break; | ||
215 | case OPT_CONNECTION_TIMEOUT: | 237 | case OPT_CONNECTION_TIMEOUT: |
216 | exec_timeout = get_timeout(optarg); | 238 | exec_timeout = get_timeout(optarg); |
217 | break; | 239 | break; |
@@ -266,12 +288,15 @@ main(int argc, char **argv) | |||
266 | json_array_flatten(ar); | 288 | json_array_flatten(ar); |
267 | json_object_set(obj, "command", ar); | 289 | json_object_set(obj, "command", ar); |
268 | 290 | ||
269 | |||
270 | rc.rc_argv = argv; | 291 | rc.rc_argv = argv; |
271 | rc.rc_timeout = exec_timeout; | 292 | rc.rc_timeout = exec_timeout; |
272 | 293 | if (rcflags & RCF_STDOUT_LINEMON) | |
294 | rc.rc_cap[RUNCAP_STDOUT].sc_linemon = stdout_linemon; | ||
295 | if (rcflags & RCF_STDERR_LINEMON) | ||
296 | rc.rc_cap[RUNCAP_STDERR].sc_linemon = stderr_linemon; | ||
297 | |||
273 | status = EX_FAILURE; | 298 | status = EX_FAILURE; |
274 | if (runcap(&rc, RCF_TIMEOUT)) { | 299 | if (runcap(&rc, rcflags)) { |
275 | json_object_set(obj, "status", json_new_bool(0)); | 300 | json_object_set(obj, "status", json_new_bool(0)); |
276 | json_object_set(obj, "error", json_new_bool(1)); | 301 | json_object_set(obj, "error", json_new_bool(1)); |
277 | json_object_set(obj, "message", | 302 | json_object_set(obj, "message", |