Support --logfile argument to make all output go to a file.

This works for both client and server side (in the case of the server,
either for daemon or non-daemon mode).

Consistifies a few places that were using printf instead of iprintf.

Fixes Issue 119.
This commit is contained in:
Bruce A. Mah 2014-03-14 14:23:38 -07:00
parent 3f5f7f7591
commit aeb6938d5a
No known key found for this signature in database
GPG Key ID: 4984910A8CAAEE8A
8 changed files with 61 additions and 13 deletions

View File

@ -174,6 +174,9 @@ struct iperf_test
char *congestion; /* -C option */ char *congestion; /* -C option */
char *pidfile; /* -P option */ char *pidfile; /* -P option */
char *logfile; /* --logfile option */
FILE *outfile;
int ctrl_sck; int ctrl_sck;
int listener; int listener;
int prot_listener; int prot_listener;

View File

@ -55,6 +55,9 @@ give more detailed output
.BR -J ", " --json " " .BR -J ", " --json " "
output in JSON format output in JSON format
.TP .TP
.BR --logfile " \fIfile\fR"
send output to a log file.
.TP
.BR -d ", " --debug " " .BR -d ", " --debug " "
emit debugging output. emit debugging output.
Primarily (perhaps exclusively) of use to developers. Primarily (perhaps exclusively) of use to developers.

View File

@ -562,6 +562,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"sctp", no_argument, NULL, OPT_SCTP}, {"sctp", no_argument, NULL, OPT_SCTP},
#endif #endif
{"pidfile", required_argument, NULL, 'I'}, {"pidfile", required_argument, NULL, 'I'},
{"logfile", required_argument, NULL, OPT_LOGFILE},
{"debug", no_argument, NULL, 'd'}, {"debug", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@ -791,6 +792,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->pidfile = strdup(optarg); test->pidfile = strdup(optarg);
server_flag = 1; server_flag = 1;
break; break;
case OPT_LOGFILE:
test->logfile = strdup(optarg);
break;
case 'h': case 'h':
default: default:
usage_long(); usage_long();
@ -798,6 +802,18 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
} }
} }
/* Set logging to a file if specified, otherwise stdout*/
if (test->logfile) {
test->outfile = fopen(test->logfile, "a+");
if (test->outfile == NULL) {
i_errno = IELOGFILE;
return -1;
}
}
else {
test->outfile = stdout;
}
/* Check flag / role compatibility. */ /* Check flag / role compatibility. */
if (test->role == 'c' && server_flag) { if (test->role == 'c' && server_flag) {
i_errno = IESERVERONLY; i_errno = IESERVERONLY;
@ -2524,9 +2540,8 @@ iperf_json_finish(struct iperf_test *test)
str = cJSON_Print(test->json_top); str = cJSON_Print(test->json_top);
if (str == NULL) if (str == NULL)
return -1; return -1;
fputs(str, stdout); fprintf(test->outfile, "%s\n", str);
putchar('\n'); iflush(test);
fflush(stdout);
free(str); free(str);
cJSON_Delete(test->json_top); cJSON_Delete(test->json_top);
test->json_top = test->json_start = test->json_intervals = test->json_end = NULL; test->json_top = test->json_start = test->json_intervals = test->json_end = NULL;
@ -2608,9 +2623,15 @@ iprintf(struct iperf_test *test, const char* format, ...)
int r; int r;
if (test->title) if (test->title)
printf("%s: ", test->title); fprintf(test->outfile, "%s: ", test->title);
va_start(argp, format); va_start(argp, format);
r = vprintf(format, argp); r = vfprintf(test->outfile, format, argp);
va_end(argp); va_end(argp);
return r; return r;
} }
int
iflush(struct iperf_test *test)
{
return fflush(test->outfile);
}

View File

@ -27,6 +27,7 @@ struct iperf_stream;
/* short option equivalents, used to support options that only have long form */ /* short option equivalents, used to support options that only have long form */
#define OPT_SCTP 1 #define OPT_SCTP 1
#define OPT_LOGFILE 2
/* states */ /* states */
#define TEST_START 1 #define TEST_START 1
@ -225,7 +226,7 @@ int iperf_clearaffinity(struct iperf_test *);
/* Custom printf routine. */ /* Custom printf routine. */
int iprintf(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3))); int iprintf(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3)));
int iflush(struct iperf_test *test);
/* Error routines. */ /* Error routines. */
void iperf_err(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3))); void iperf_err(struct iperf_test *test, const char *format, ...) __attribute__ ((format(printf,2,3)));
@ -251,6 +252,7 @@ enum {
IEFILE = 14, // -F file couldn't be opened IEFILE = 14, // -F file couldn't be opened
IEBURST = 15, // Invalid burst count. Maximum value = %dMAX_BURST IEBURST = 15, // Invalid burst count. Maximum value = %dMAX_BURST
IEENDCONDITIONS = 16, // Only one test end condition (-t, -n, -k) may be specified IEENDCONDITIONS = 16, // Only one test end condition (-t, -n, -k) may be specified
IELOGFILE = 17, // Can't open log file
/* Test errors */ /* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror) IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror) IEINITTEST = 101, // Test initialization failed (check perror)

View File

@ -356,7 +356,7 @@ iperf_run_client(struct iperf_test * test)
iprintf(test, "%s\n", version); iprintf(test, "%s\n", version);
iprintf(test, "%s", ""); iprintf(test, "%s", "");
fflush(stdout); fflush(stdout);
printf("%s\n", get_system_info()); iprintf("%s\n", get_system_info());
} }
/* Start the client and connect to the server */ /* Start the client and connect to the server */
@ -479,5 +479,7 @@ iperf_run_client(struct iperf_test * test)
iprintf(test, "%s", report_done); iprintf(test, "%s", report_done);
} }
iflush(test);
return 0; return 0;
} }

View File

@ -28,11 +28,16 @@ iperf_err(struct iperf_test *test, const char *format, ...)
if (test != NULL && test->json_output && test->json_top != NULL) if (test != NULL && test->json_output && test->json_top != NULL)
cJSON_AddStringToObject(test->json_top, "error", str); cJSON_AddStringToObject(test->json_top, "error", str);
else else
fprintf(stderr, "iperf3: %s\n", str); if (test && test->outfile) {
fprintf(test->outfile, "iperf3: %s\n", str);
}
else {
fprintf(stderr, "iperf3: %s\n", str);
}
va_end(argp); va_end(argp);
} }
/* Do a printf to stderr, then exit. */ /* Do a printf to stderr or log file as appropriate, then exit. */
void void
iperf_errexit(struct iperf_test *test, const char *format, ...) iperf_errexit(struct iperf_test *test, const char *format, ...)
{ {
@ -45,7 +50,12 @@ iperf_errexit(struct iperf_test *test, const char *format, ...)
cJSON_AddStringToObject(test->json_top, "error", str); cJSON_AddStringToObject(test->json_top, "error", str);
iperf_json_finish(test); iperf_json_finish(test);
} else } else
fprintf(stderr, "iperf3: %s\n", str); if (test && test->outfile) {
fprintf(test->outfile, "iperf3: %s\n", str);
}
else {
fprintf(stderr, "iperf3: %s\n", str);
}
va_end(argp); va_end(argp);
iperf_delete_pidfile(test); iperf_delete_pidfile(test);
exit(1); exit(1);
@ -116,6 +126,10 @@ iperf_strerror(int i_errno)
case IEENDCONDITIONS: case IEENDCONDITIONS:
snprintf(errstr, len, "only one test end condition (-t, -n, -k) may be specified"); snprintf(errstr, len, "only one test end condition (-t, -n, -k) may be specified");
break; break;
case IELOGFILE:
snprintf(errstr, len, "unable to open log file");
perr = 1;
break;
case IENEWTEST: case IENEWTEST:
snprintf(errstr, len, "unable to create a new test"); snprintf(errstr, len, "unable to create a new test");
perr = 1; perr = 1;

View File

@ -65,8 +65,8 @@ iperf_server_listen(struct iperf_test *test)
} }
if (!test->json_output) { if (!test->json_output) {
printf("-----------------------------------------------------------\n"); iprintf(test, "-----------------------------------------------------------\n");
printf("Server listening on %d\n", test->server_port); iprintf(test, "Server listening on %d\n", test->server_port);
} }
// This needs to be changed to reflect if client has different window size // This needs to be changed to reflect if client has different window size
@ -450,7 +450,7 @@ iperf_run_server(struct iperf_test *test)
iprintf(test, "%s\n", version); iprintf(test, "%s\n", version);
iprintf(test, "%s", ""); iprintf(test, "%s", "");
fflush(stdout); fflush(stdout);
printf("%s\n", get_system_info()); iprintf(test, "%s\n", get_system_info());
} }
// Open socket and listen // Open socket and listen
@ -602,6 +602,8 @@ iperf_run_server(struct iperf_test *test)
return -1; return -1;
} }
iflush(test);
if (test->server_affinity != -1) if (test->server_affinity != -1)
if (iperf_clearaffinity(test) != 0) if (iperf_clearaffinity(test) != 0)
return -1; return -1;

View File

@ -78,6 +78,7 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
#endif #endif
" -V, --verbose more detailed output\n" " -V, --verbose more detailed output\n"
" -J, --json output in JSON format\n" " -J, --json output in JSON format\n"
" --logfile f send output to a log file\n"
" -d, --debug emit debugging output\n" " -d, --debug emit debugging output\n"
" -v, --version show version information and quit\n" " -v, --version show version information and quit\n"
" -h, --help show this message and quit\n" " -h, --help show this message and quit\n"