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", |
