diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-03-29 17:08:24 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-03-29 17:08:24 -0400 |
commit | 47d850792f4e2340cbd53b6cf76bc16125d66fd4 (patch) | |
tree | bde31cc35e1490a30b4f5684510aa0a49f326d62 | |
parent | 3d85518bf58a7052ff18e2c33547ceefac5c1939 (diff) |
trace-cmd: Add -l option to trace-cmd listen for log file output
Add a way to pipe log info to another file, especially useful in
daemon mode.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | Documentation/trace-cmd-listen.1.txt | 3 | ||||
-rw-r--r-- | trace-listen.c | 98 | ||||
-rw-r--r-- | trace-usage.c | 3 |
3 files changed, 83 insertions, 21 deletions
diff --git a/Documentation/trace-cmd-listen.1.txt b/Documentation/trace-cmd-listen.1.txt index 15014e6..c9bafcd 100644 --- a/Documentation/trace-cmd-listen.1.txt +++ b/Documentation/trace-cmd-listen.1.txt | |||
@@ -33,6 +33,9 @@ OPTIONS | |||
33 | This option overrides the default 'trace' in the 'trace.HOST:PORT.dat' that | 33 | This option overrides the default 'trace' in the 'trace.HOST:PORT.dat' that |
34 | is created when a remote host connects. | 34 | is created when a remote host connects. |
35 | 35 | ||
36 | *-l* 'filename':: | ||
37 | This option writes the output messages to a log file instead of standard output. | ||
38 | |||
36 | 39 | ||
37 | SEE ALSO | 40 | SEE ALSO |
38 | -------- | 41 | -------- |
diff --git a/trace-listen.c b/trace-listen.c index e12431c..9564620 100644 --- a/trace-listen.c +++ b/trace-listen.c | |||
@@ -43,6 +43,8 @@ static char *output_dir; | |||
43 | static char *default_output_file = "trace"; | 43 | static char *default_output_file = "trace"; |
44 | static char *output_file; | 44 | static char *output_file; |
45 | 45 | ||
46 | static FILE *logfp; | ||
47 | |||
46 | static int debug; | 48 | static int debug; |
47 | 49 | ||
48 | static int use_tcp; | 50 | static int use_tcp; |
@@ -107,6 +109,51 @@ static void finish(int sig) | |||
107 | done = 1; | 109 | done = 1; |
108 | } | 110 | } |
109 | 111 | ||
112 | #define LOG_BUF_SIZE 1024 | ||
113 | static void __plog(const char *prefix, const char *fmt, va_list ap, | ||
114 | FILE *fp) | ||
115 | { | ||
116 | static int newline = 1; | ||
117 | char buf[LOG_BUF_SIZE]; | ||
118 | int r; | ||
119 | |||
120 | r = vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); | ||
121 | |||
122 | if (r > LOG_BUF_SIZE) | ||
123 | r = LOG_BUF_SIZE; | ||
124 | |||
125 | if (logfp) { | ||
126 | if (newline) | ||
127 | fprintf(logfp, "[%d]%s%.*s", getpid(), prefix, r, buf); | ||
128 | else | ||
129 | fprintf(logfp, "[%d]%s%.*s", getpid(), prefix, r, buf); | ||
130 | newline = buf[r - 1] == '\n'; | ||
131 | fflush(logfp); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | fprintf(fp, "%.*s", r, buf); | ||
136 | } | ||
137 | |||
138 | static void plog(const char *fmt, ...) | ||
139 | { | ||
140 | va_list ap; | ||
141 | |||
142 | va_start(ap, fmt); | ||
143 | __plog("", fmt, ap, stdout); | ||
144 | va_end(ap); | ||
145 | } | ||
146 | |||
147 | static void pdie(const char *fmt, ...) | ||
148 | { | ||
149 | va_list ap; | ||
150 | |||
151 | va_start(ap, fmt); | ||
152 | __plog("Error: ", fmt, ap, stderr); | ||
153 | va_end(ap); | ||
154 | exit(-1); | ||
155 | } | ||
156 | |||
110 | static void process_udp_child(int sfd, const char *host, const char *port, | 157 | static void process_udp_child(int sfd, const char *host, const char *port, |
111 | int cpu, int page_size) | 158 | int cpu, int page_size) |
112 | { | 159 | { |
@@ -124,15 +171,15 @@ static void process_udp_child(int sfd, const char *host, const char *port, | |||
124 | tempfile = get_temp_file(host, port, cpu); | 171 | tempfile = get_temp_file(host, port, cpu); |
125 | fd = open(tempfile, O_WRONLY | O_TRUNC | O_CREAT, 0644); | 172 | fd = open(tempfile, O_WRONLY | O_TRUNC | O_CREAT, 0644); |
126 | if (fd < 0) | 173 | if (fd < 0) |
127 | die("creating %s", tempfile); | 174 | pdie("creating %s", tempfile); |
128 | 175 | ||
129 | if (use_tcp) { | 176 | if (use_tcp) { |
130 | if (listen(sfd, backlog) < 0) | 177 | if (listen(sfd, backlog) < 0) |
131 | die("listen"); | 178 | pdie("listen"); |
132 | peer_addr_len = sizeof(peer_addr); | 179 | peer_addr_len = sizeof(peer_addr); |
133 | cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len); | 180 | cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len); |
134 | if (cfd < 0) | 181 | if (cfd < 0) |
135 | die("accept"); | 182 | pdie("accept"); |
136 | close(sfd); | 183 | close(sfd); |
137 | sfd = cfd; | 184 | sfd = cfd; |
138 | } | 185 | } |
@@ -141,7 +188,7 @@ static void process_udp_child(int sfd, const char *host, const char *port, | |||
141 | /* TODO, make this copyless! */ | 188 | /* TODO, make this copyless! */ |
142 | n = read(sfd, buf, page_size); | 189 | n = read(sfd, buf, page_size); |
143 | if (n < 0) | 190 | if (n < 0) |
144 | die("reading client"); | 191 | pdie("reading client"); |
145 | if (!n) | 192 | if (!n) |
146 | break; | 193 | break; |
147 | /* UDP requires that we get the full size in one go */ | 194 | /* UDP requires that we get the full size in one go */ |
@@ -178,7 +225,7 @@ static int open_udp(const char *node, const char *port, int *pid, | |||
178 | 225 | ||
179 | s = getaddrinfo(NULL, buf, &hints, &result); | 226 | s = getaddrinfo(NULL, buf, &hints, &result); |
180 | if (s != 0) | 227 | if (s != 0) |
181 | die("getaddrinfo: error opening udp socket"); | 228 | pdie("getaddrinfo: error opening udp socket"); |
182 | 229 | ||
183 | for (rp = result; rp != NULL; rp = rp->ai_next) { | 230 | for (rp = result; rp != NULL; rp = rp->ai_next) { |
184 | sfd = socket(rp->ai_family, rp->ai_socktype, | 231 | sfd = socket(rp->ai_family, rp->ai_socktype, |
@@ -195,7 +242,7 @@ static int open_udp(const char *node, const char *port, int *pid, | |||
195 | if (rp == NULL) { | 242 | if (rp == NULL) { |
196 | freeaddrinfo(result); | 243 | freeaddrinfo(result); |
197 | if (++num_port > MAX_PORT_SEARCH) | 244 | if (++num_port > MAX_PORT_SEARCH) |
198 | die("No available ports to bind"); | 245 | pdie("No available ports to bind"); |
199 | goto again; | 246 | goto again; |
200 | } | 247 | } |
201 | 248 | ||
@@ -204,7 +251,7 @@ static int open_udp(const char *node, const char *port, int *pid, | |||
204 | *pid = fork(); | 251 | *pid = fork(); |
205 | 252 | ||
206 | if (*pid < 0) | 253 | if (*pid < 0) |
207 | die("creating udp reader"); | 254 | pdie("creating udp reader"); |
208 | 255 | ||
209 | if (!*pid) | 256 | if (!*pid) |
210 | process_udp_child(sfd, node, port, cpu, pagesize); | 257 | process_udp_child(sfd, node, port, cpu, pagesize); |
@@ -242,7 +289,7 @@ static void process_client(const char *node, const char *port, int fd) | |||
242 | 289 | ||
243 | cpus = atoi(buf); | 290 | cpus = atoi(buf); |
244 | 291 | ||
245 | printf("cpus=%d\n", cpus); | 292 | plog("cpus=%d\n", cpus); |
246 | if (cpus < 0) | 293 | if (cpus < 0) |
247 | return; | 294 | return; |
248 | 295 | ||
@@ -254,7 +301,7 @@ static void process_client(const char *node, const char *port, int fd) | |||
254 | 301 | ||
255 | pagesize = atoi(buf); | 302 | pagesize = atoi(buf); |
256 | 303 | ||
257 | printf("pagesize=%d\n", pagesize); | 304 | plog("pagesize=%d\n", pagesize); |
258 | if (pagesize <= 0) | 305 | if (pagesize <= 0) |
259 | return; | 306 | return; |
260 | 307 | ||
@@ -295,14 +342,14 @@ static void process_client(const char *node, const char *port, int fd) | |||
295 | } | 342 | } |
296 | 343 | ||
297 | if (use_tcp) | 344 | if (use_tcp) |
298 | printf("Using TCP for live connection\n"); | 345 | plog("Using TCP for live connection\n"); |
299 | 346 | ||
300 | /* Create the client file */ | 347 | /* Create the client file */ |
301 | snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port); | 348 | snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port); |
302 | 349 | ||
303 | ofd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0644); | 350 | ofd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0644); |
304 | if (ofd < 0) | 351 | if (ofd < 0) |
305 | die("Can not create file %s", buf); | 352 | pdie("Can not create file %s", buf); |
306 | 353 | ||
307 | port_array = malloc_or_die(sizeof(int) * cpus); | 354 | port_array = malloc_or_die(sizeof(int) * cpus); |
308 | pid_array = malloc_or_die(sizeof(int) * cpus); | 355 | pid_array = malloc_or_die(sizeof(int) * cpus); |
@@ -334,7 +381,7 @@ static void process_client(const char *node, const char *port, int fd) | |||
334 | do { | 381 | do { |
335 | s = write(ofd, buf+s, t); | 382 | s = write(ofd, buf+s, t); |
336 | if (s < 0) | 383 | if (s < 0) |
337 | die("writing to file"); | 384 | pdie("writing to file"); |
338 | t -= s; | 385 | t -= s; |
339 | s = n - t; | 386 | s = n - t; |
340 | } while (t); | 387 | } while (t); |
@@ -410,10 +457,10 @@ static void do_connection(int cfd, struct sockaddr_storage *peer_addr, | |||
410 | service, NI_MAXSERV, NI_NUMERICSERV); | 457 | service, NI_MAXSERV, NI_NUMERICSERV); |
411 | 458 | ||
412 | if (s == 0) | 459 | if (s == 0) |
413 | printf("Connected with %s:%s\n", | 460 | plog("Connected with %s:%s\n", |
414 | host, service); | 461 | host, service); |
415 | else { | 462 | else { |
416 | printf("Error with getnameinfo: %s\n", | 463 | plog("Error with getnameinfo: %s\n", |
417 | gai_strerror(s)); | 464 | gai_strerror(s)); |
418 | close(cfd); | 465 | close(cfd); |
419 | return; | 466 | return; |
@@ -425,7 +472,7 @@ static void do_connection(int cfd, struct sockaddr_storage *peer_addr, | |||
425 | if (nread > 0) | 472 | if (nread > 0) |
426 | nread = read(cfd, buf, BUFSIZ); | 473 | nread = read(cfd, buf, BUFSIZ); |
427 | if (cfd < 0) | 474 | if (cfd < 0) |
428 | die("client"); | 475 | pdie("client"); |
429 | if (nread > 0) | 476 | if (nread > 0) |
430 | write(1, buf, nread); | 477 | write(1, buf, nread); |
431 | } while (nread); | 478 | } while (nread); |
@@ -465,7 +512,7 @@ static void do_listen(char *port) | |||
465 | 512 | ||
466 | s = getaddrinfo(NULL, port, &hints, &result); | 513 | s = getaddrinfo(NULL, port, &hints, &result); |
467 | if (s != 0) | 514 | if (s != 0) |
468 | die("getaddrinfo: error opening %s", port); | 515 | pdie("getaddrinfo: error opening %s", port); |
469 | 516 | ||
470 | for (rp = result; rp != NULL; rp = rp->ai_next) { | 517 | for (rp = result; rp != NULL; rp = rp->ai_next) { |
471 | sfd = socket(rp->ai_family, rp->ai_socktype, | 518 | sfd = socket(rp->ai_family, rp->ai_socktype, |
@@ -480,19 +527,19 @@ static void do_listen(char *port) | |||
480 | } | 527 | } |
481 | 528 | ||
482 | if (rp == NULL) | 529 | if (rp == NULL) |
483 | die("Could not bind"); | 530 | pdie("Could not bind"); |
484 | 531 | ||
485 | freeaddrinfo(result); | 532 | freeaddrinfo(result); |
486 | 533 | ||
487 | if (listen(sfd, backlog) < 0) | 534 | if (listen(sfd, backlog) < 0) |
488 | die("listen"); | 535 | pdie("listen"); |
489 | 536 | ||
490 | peer_addr_len = sizeof(peer_addr); | 537 | peer_addr_len = sizeof(peer_addr); |
491 | 538 | ||
492 | do { | 539 | do { |
493 | cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len); | 540 | cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len); |
494 | if (cfd < 0) | 541 | if (cfd < 0) |
495 | die("connecting"); | 542 | pdie("connecting"); |
496 | 543 | ||
497 | do_connection(cfd, &peer_addr, peer_addr_len); | 544 | do_connection(cfd, &peer_addr, peer_addr_len); |
498 | 545 | ||
@@ -507,6 +554,7 @@ static void start_daemon(void) | |||
507 | 554 | ||
508 | void trace_listen(int argc, char **argv) | 555 | void trace_listen(int argc, char **argv) |
509 | { | 556 | { |
557 | char *logfile = NULL; | ||
510 | char *port = NULL; | 558 | char *port = NULL; |
511 | char *iface; | 559 | char *iface; |
512 | int daemon = 0; | 560 | int daemon = 0; |
@@ -527,7 +575,7 @@ void trace_listen(int argc, char **argv) | |||
527 | {NULL, 0, NULL, 0} | 575 | {NULL, 0, NULL, 0} |
528 | }; | 576 | }; |
529 | 577 | ||
530 | c = getopt_long (argc-1, argv+1, "+hp:o:d:i:D", | 578 | c = getopt_long (argc-1, argv+1, "+hp:o:d:i:l:D", |
531 | long_options, &option_index); | 579 | long_options, &option_index); |
532 | if (c == -1) | 580 | if (c == -1) |
533 | break; | 581 | break; |
@@ -547,6 +595,9 @@ void trace_listen(int argc, char **argv) | |||
547 | case 'o': | 595 | case 'o': |
548 | output_file = optarg; | 596 | output_file = optarg; |
549 | break; | 597 | break; |
598 | case 'l': | ||
599 | logfile = optarg; | ||
600 | break; | ||
550 | case 'D': | 601 | case 'D': |
551 | daemon = 1; | 602 | daemon = 1; |
552 | break; | 603 | break; |
@@ -574,6 +625,13 @@ void trace_listen(int argc, char **argv) | |||
574 | if (!output_dir) | 625 | if (!output_dir) |
575 | output_dir = default_output_dir; | 626 | output_dir = default_output_dir; |
576 | 627 | ||
628 | if (logfile) { | ||
629 | /* set the writes to a logfile instead */ | ||
630 | logfp = fopen(logfile, "w"); | ||
631 | if (!logfp) | ||
632 | die("creating log file %s", logfile); | ||
633 | } | ||
634 | |||
577 | if (chdir(output_dir) < 0) | 635 | if (chdir(output_dir) < 0) |
578 | die("Can't access directory %s", output_dir); | 636 | die("Can't access directory %s", output_dir); |
579 | 637 | ||
diff --git a/trace-usage.c b/trace-usage.c index 828fdd0..e834d44 100644 --- a/trace-usage.c +++ b/trace-usage.c | |||
@@ -104,11 +104,12 @@ static struct usage_help usage_help[] = { | |||
104 | { | 104 | { |
105 | "listen", | 105 | "listen", |
106 | "listen on a network socket for trace clients", | 106 | "listen on a network socket for trace clients", |
107 | " %s listen -p port[-D][-o file][-d dir]\n" | 107 | " %s listen -p port[-D][-o file][-d dir][-l logfile]\n" |
108 | " Creates a socket to listen for clients.\n" | 108 | " Creates a socket to listen for clients.\n" |
109 | " -D create it in daemon mode.\n" | 109 | " -D create it in daemon mode.\n" |
110 | " -o file name to use for clients.\n" | 110 | " -o file name to use for clients.\n" |
111 | " -d diretory to store client files.\n" | 111 | " -d diretory to store client files.\n" |
112 | " -l logfile to write messages to.\n" | ||
112 | }, | 113 | }, |
113 | { | 114 | { |
114 | "list", | 115 | "list", |