logs-show: various cleanups
Among other cleanups this introduces a threshold for the size of binary blobs we serialize as integer arrays in the JSON output. THis can be disabled via --all.
This commit is contained in:
parent
8f14c8327b
commit
08ace05beb
|
@ -730,7 +730,6 @@ static int verify(sd_journal *j) {
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int r;
|
int r;
|
||||||
sd_journal *j = NULL;
|
sd_journal *j = NULL;
|
||||||
unsigned line = 0;
|
|
||||||
bool need_seek = false;
|
bool need_seek = false;
|
||||||
sd_id128_t previous_boot_id;
|
sd_id128_t previous_boot_id;
|
||||||
bool previous_boot_id_valid = false;
|
bool previous_boot_id_valid = false;
|
||||||
|
@ -904,9 +903,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line ++;
|
r = output_journal(stdout, j, arg_output, 0, flags);
|
||||||
|
|
||||||
r = output_journal(j, arg_output, line, 0, flags);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
|
||||||
#define PRINT_THRESHOLD 128
|
#define PRINT_THRESHOLD 128
|
||||||
|
#define JSON_THRESHOLD 4096
|
||||||
|
|
||||||
static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
|
static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
|
||||||
size_t fl, nl;
|
size_t fl, nl;
|
||||||
|
@ -63,8 +64,10 @@ static int parse_field(const void *data, size_t length, const char *field, char
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool shall_print(bool show_all, char *p, size_t l) {
|
static bool shall_print(const char *p, size_t l, OutputFlags flags) {
|
||||||
if (show_all)
|
assert(p);
|
||||||
|
|
||||||
|
if (flags & OUTPUT_SHOW_ALL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (l > PRINT_THRESHOLD)
|
if (l > PRINT_THRESHOLD)
|
||||||
|
@ -76,78 +79,82 @@ static bool shall_print(bool show_all, char *p, size_t l) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns,
|
static int output_short(
|
||||||
OutputFlags flags) {
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
const void *data;
|
const void *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
|
_cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
|
||||||
size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0;
|
size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0;
|
||||||
int p = LOG_INFO;
|
int p = LOG_INFO;
|
||||||
const char *color_on = "", *color_off = "";
|
const char *color_on = "", *color_off = "";
|
||||||
|
|
||||||
|
assert(f);
|
||||||
assert(j);
|
assert(j);
|
||||||
|
|
||||||
SD_JOURNAL_FOREACH_DATA(j, data, length) {
|
SD_JOURNAL_FOREACH_DATA(j, data, length) {
|
||||||
|
|
||||||
r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
|
r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
|
r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
|
r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "_COMM=", &comm, &comm_len);
|
r = parse_field(data, length, "_COMM=", &comm, &comm_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "_PID=", &pid, &pid_len);
|
r = parse_field(data, length, "_PID=", &pid, &pid_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
|
r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
|
r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
|
r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = parse_field(data, length, "MESSAGE=", &message, &message_len);
|
r = parse_field(data, length, "MESSAGE=", &message, &message_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message) {
|
if (!message)
|
||||||
r = 0;
|
return 0;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priority_len == 1 && *priority >= '0' && *priority <= '7')
|
if (priority_len == 1 && *priority >= '0' && *priority <= '7')
|
||||||
p = *priority - '0';
|
p = *priority - '0';
|
||||||
|
@ -166,12 +173,12 @@ static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error("Failed to get monotonic: %s", strerror(-r));
|
log_error("Failed to get monotonic: %s", strerror(-r));
|
||||||
goto finish;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[%5llu.%06llu]",
|
fprintf(f, "[%5llu.%06llu]",
|
||||||
(unsigned long long) (t / USEC_PER_SEC),
|
(unsigned long long) (t / USEC_PER_SEC),
|
||||||
(unsigned long long) (t % USEC_PER_SEC));
|
(unsigned long long) (t % USEC_PER_SEC));
|
||||||
|
|
||||||
n += 1 + 5 + 1 + 6 + 1;
|
n += 1 + 5 + 1 + 6 + 1;
|
||||||
|
|
||||||
|
@ -191,42 +198,38 @@ static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error("Failed to get realtime: %s", strerror(-r));
|
log_error("Failed to get realtime: %s", strerror(-r));
|
||||||
goto finish;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = (time_t) (x / USEC_PER_SEC);
|
t = (time_t) (x / USEC_PER_SEC);
|
||||||
if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
|
if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
|
||||||
log_error("Failed to format time.");
|
log_error("Failed to format time.");
|
||||||
goto finish;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs(buf, stdout);
|
fputs(buf, f);
|
||||||
n += strlen(buf);
|
n += strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostname && shall_print(flags & OUTPUT_SHOW_ALL,
|
if (hostname && shall_print(hostname, hostname_len, flags)) {
|
||||||
hostname, hostname_len)) {
|
fprintf(f, " %.*s", (int) hostname_len, hostname);
|
||||||
printf(" %.*s", (int) hostname_len, hostname);
|
|
||||||
n += hostname_len + 1;
|
n += hostname_len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identifier && shall_print(flags & OUTPUT_SHOW_ALL,
|
if (identifier && shall_print(identifier, identifier_len, flags)) {
|
||||||
identifier, identifier_len)) {
|
fprintf(f, " %.*s", (int) identifier_len, identifier);
|
||||||
printf(" %.*s", (int) identifier_len, identifier);
|
|
||||||
n += identifier_len + 1;
|
n += identifier_len + 1;
|
||||||
} else if (comm && shall_print(flags & OUTPUT_SHOW_ALL,
|
} else if (comm && shall_print(comm, comm_len, flags)) {
|
||||||
comm, comm_len)) {
|
fprintf(f, " %.*s", (int) comm_len, comm);
|
||||||
printf(" %.*s", (int) comm_len, comm);
|
|
||||||
n += comm_len + 1;
|
n += comm_len + 1;
|
||||||
} else
|
} else
|
||||||
putchar(' ');
|
fputc(' ', f);
|
||||||
|
|
||||||
if (pid && shall_print(flags & OUTPUT_SHOW_ALL, pid, pid_len)) {
|
if (pid && shall_print(pid, pid_len, flags)) {
|
||||||
printf("[%.*s]", (int) pid_len, pid);
|
fprintf(f, "[%.*s]", (int) pid_len, pid);
|
||||||
n += pid_len + 2;
|
n += pid_len + 2;
|
||||||
} else if (fake_pid && shall_print(flags & OUTPUT_SHOW_ALL,
|
} else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
|
||||||
fake_pid, fake_pid_len)) {
|
fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
|
||||||
printf("[%.*s]", (int) fake_pid_len, fake_pid);
|
|
||||||
n += fake_pid_len + 2;
|
n += fake_pid_len + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,46 +243,37 @@ static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & OUTPUT_SHOW_ALL)
|
if (flags)
|
||||||
printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
|
fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
|
||||||
else if (!utf8_is_printable_n(message, message_len)) {
|
else if (!utf8_is_printable_n(message, message_len)) {
|
||||||
char bytes[FORMAT_BYTES_MAX];
|
char bytes[FORMAT_BYTES_MAX];
|
||||||
printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
|
fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
|
||||||
} else if ((flags & OUTPUT_FULL_WIDTH) ||
|
} else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n + 1 < n_columns))
|
||||||
(message_len + n + 1 < n_columns))
|
fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
|
||||||
printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
|
|
||||||
else if (n < n_columns && n_columns - n - 2 >= 3) {
|
else if (n < n_columns && n_columns - n - 2 >= 3) {
|
||||||
char *e;
|
char *e;
|
||||||
|
|
||||||
e = ellipsize_mem(message, message_len, n_columns - n - 2, 90);
|
e = ellipsize_mem(message, message_len, n_columns - n - 2, 90);
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
|
fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
|
||||||
else
|
else
|
||||||
printf(": %s%s%s\n", color_on, e, color_off);
|
fprintf(f, ": %s%s%s\n", color_on, e, color_off);
|
||||||
|
|
||||||
free(e);
|
free(e);
|
||||||
} else
|
} else
|
||||||
fputs("\n", stdout);
|
fputs("\n", f);
|
||||||
|
|
||||||
r = 0;
|
return 0;
|
||||||
|
|
||||||
finish:
|
|
||||||
free(hostname);
|
|
||||||
free(identifier);
|
|
||||||
free(comm);
|
|
||||||
free(pid);
|
|
||||||
free(fake_pid);
|
|
||||||
free(message);
|
|
||||||
free(monotonic);
|
|
||||||
free(realtime);
|
|
||||||
free(priority);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_verbose(sd_journal *j, OutputMode mode, unsigned line,
|
static int output_verbose(
|
||||||
unsigned n_columns, OutputFlags flags) {
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
const void *data;
|
const void *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
char *cursor;
|
char *cursor;
|
||||||
|
@ -287,6 +281,7 @@ static int output_verbose(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
char ts[FORMAT_TIMESTAMP_MAX];
|
char ts[FORMAT_TIMESTAMP_MAX];
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(f);
|
||||||
assert(j);
|
assert(j);
|
||||||
|
|
||||||
r = sd_journal_get_realtime_usec(j, &realtime);
|
r = sd_journal_get_realtime_usec(j, &realtime);
|
||||||
|
@ -301,15 +296,14 @@ static int output_verbose(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s [%s]\n",
|
fprintf(f, "%s [%s]\n",
|
||||||
format_timestamp(ts, sizeof(ts), realtime),
|
format_timestamp(ts, sizeof(ts), realtime),
|
||||||
cursor);
|
cursor);
|
||||||
|
|
||||||
free(cursor);
|
free(cursor);
|
||||||
|
|
||||||
SD_JOURNAL_FOREACH_DATA(j, data, length) {
|
SD_JOURNAL_FOREACH_DATA(j, data, length) {
|
||||||
if (!(flags & OUTPUT_SHOW_ALL) && (length > PRINT_THRESHOLD ||
|
if (!shall_print(data, length, flags)) {
|
||||||
!utf8_is_printable_n(data, length))) {
|
|
||||||
const char *c;
|
const char *c;
|
||||||
char bytes[FORMAT_BYTES_MAX];
|
char bytes[FORMAT_BYTES_MAX];
|
||||||
|
|
||||||
|
@ -319,19 +313,24 @@ static int output_verbose(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\t%.*s=[%s blob data]\n",
|
fprintf(f, "\t%.*s=[%s blob data]\n",
|
||||||
(int) (c - (const char*) data),
|
(int) (c - (const char*) data),
|
||||||
(const char*) data,
|
(const char*) data,
|
||||||
format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
|
format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
|
||||||
} else
|
} else
|
||||||
printf("\t%.*s\n", (int) length, (const char*) data);
|
fprintf(f, "\t%.*s\n", (int) length, (const char*) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_export(sd_journal *j, OutputMode mode, unsigned line,
|
static int output_export(
|
||||||
unsigned n_columns, OutputFlags flags) {
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
sd_id128_t boot_id;
|
sd_id128_t boot_id;
|
||||||
char sid[33];
|
char sid[33];
|
||||||
int r;
|
int r;
|
||||||
|
@ -360,14 +359,15 @@ static int output_export(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("__CURSOR=%s\n"
|
fprintf(f,
|
||||||
"__REALTIME_TIMESTAMP=%llu\n"
|
"__CURSOR=%s\n"
|
||||||
"__MONOTONIC_TIMESTAMP=%llu\n"
|
"__REALTIME_TIMESTAMP=%llu\n"
|
||||||
"_BOOT_ID=%s\n",
|
"__MONOTONIC_TIMESTAMP=%llu\n"
|
||||||
cursor,
|
"_BOOT_ID=%s\n",
|
||||||
(unsigned long long) realtime,
|
cursor,
|
||||||
(unsigned long long) monotonic,
|
(unsigned long long) realtime,
|
||||||
sd_id128_to_string(boot_id, sid));
|
(unsigned long long) monotonic,
|
||||||
|
sd_id128_to_string(boot_id, sid));
|
||||||
|
|
||||||
free(cursor);
|
free(cursor);
|
||||||
|
|
||||||
|
@ -389,61 +389,80 @@ static int output_export(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(data, c - (const char*) data, 1, stdout);
|
fwrite(data, c - (const char*) data, 1, f);
|
||||||
fputc('\n', stdout);
|
fputc('\n', f);
|
||||||
le64 = htole64(length - (c - (const char*) data) - 1);
|
le64 = htole64(length - (c - (const char*) data) - 1);
|
||||||
fwrite(&le64, sizeof(le64), 1, stdout);
|
fwrite(&le64, sizeof(le64), 1, f);
|
||||||
fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout);
|
fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
|
||||||
} else
|
} else
|
||||||
fwrite(data, length, 1, stdout);
|
fwrite(data, length, 1, f);
|
||||||
|
|
||||||
fputc('\n', stdout);
|
fputc('\n', f);
|
||||||
}
|
}
|
||||||
|
|
||||||
fputc('\n', stdout);
|
fputc('\n', f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void json_escape(const char* p, size_t l) {
|
static void json_escape(
|
||||||
if (!utf8_is_printable_n(p, l)) {
|
FILE *f,
|
||||||
|
const char* p,
|
||||||
|
size_t l,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
if (!(flags & OUTPUT_SHOW_ALL) && l > JSON_THRESHOLD)
|
||||||
|
|
||||||
|
fputs("null", f);
|
||||||
|
|
||||||
|
else if (!utf8_is_printable_n(p, l)) {
|
||||||
bool not_first = false;
|
bool not_first = false;
|
||||||
|
|
||||||
fputs("[ ", stdout);
|
fputs("[ ", f);
|
||||||
|
|
||||||
while (l > 0) {
|
while (l > 0) {
|
||||||
if (not_first)
|
if (not_first)
|
||||||
printf(", %u", (uint8_t) *p);
|
fprintf(f, ", %u", (uint8_t) *p);
|
||||||
else {
|
else {
|
||||||
not_first = true;
|
not_first = true;
|
||||||
printf("%u", (uint8_t) *p);
|
fprintf(f, "%u", (uint8_t) *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs(" ]", stdout);
|
fputs(" ]", f);
|
||||||
} else {
|
} else {
|
||||||
fputc('\"', stdout);
|
fputc('\"', f);
|
||||||
|
|
||||||
while (l > 0) {
|
while (l > 0) {
|
||||||
if (*p == '"' || *p == '\\') {
|
if (*p == '"' || *p == '\\') {
|
||||||
fputc('\\', stdout);
|
fputc('\\', f);
|
||||||
fputc(*p, stdout);
|
fputc(*p, f);
|
||||||
} else
|
} else if (*p < ' ')
|
||||||
fputc(*p, stdout);
|
fprintf(f, "\\u%04x", *p);
|
||||||
|
else
|
||||||
|
fputc(*p, f);
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputc('\"', stdout);
|
fputc('\"', f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_json(sd_journal *j, OutputMode mode, unsigned line,
|
static int output_json(
|
||||||
unsigned n_columns, OutputFlags flags) {
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
uint64_t realtime, monotonic;
|
uint64_t realtime, monotonic;
|
||||||
char *cursor;
|
char *cursor;
|
||||||
const void *data;
|
const void *data;
|
||||||
|
@ -473,24 +492,26 @@ static int output_json(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == OUTPUT_JSON_PRETTY)
|
if (mode == OUTPUT_JSON_PRETTY)
|
||||||
printf("{\n"
|
fprintf(f,
|
||||||
"\t\"__CURSOR\" : \"%s\",\n"
|
"{\n"
|
||||||
"\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
|
"\t\"__CURSOR\" : \"%s\",\n"
|
||||||
"\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
|
"\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
|
||||||
"\t\"_BOOT_ID\" : \"%s\"",
|
"\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
|
||||||
cursor,
|
"\t\"_BOOT_ID\" : \"%s\"",
|
||||||
(unsigned long long) realtime,
|
cursor,
|
||||||
(unsigned long long) monotonic,
|
(unsigned long long) realtime,
|
||||||
sd_id128_to_string(boot_id, sid));
|
(unsigned long long) monotonic,
|
||||||
|
sd_id128_to_string(boot_id, sid));
|
||||||
else
|
else
|
||||||
printf("{ \"__CURSOR\" : \"%s\", "
|
fprintf(f,
|
||||||
"\"__REALTIME_TIMESTAMP\" : \"%llu\", "
|
"{ \"__CURSOR\" : \"%s\", "
|
||||||
"\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
|
"\"__REALTIME_TIMESTAMP\" : \"%llu\", "
|
||||||
"\"_BOOT_ID\" : \"%s\"",
|
"\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
|
||||||
cursor,
|
"\"_BOOT_ID\" : \"%s\"",
|
||||||
(unsigned long long) realtime,
|
cursor,
|
||||||
(unsigned long long) monotonic,
|
(unsigned long long) realtime,
|
||||||
sd_id128_to_string(boot_id, sid));
|
(unsigned long long) monotonic,
|
||||||
|
sd_id128_to_string(boot_id, sid));
|
||||||
free(cursor);
|
free(cursor);
|
||||||
|
|
||||||
SD_JOURNAL_FOREACH_DATA(j, data, length) {
|
SD_JOURNAL_FOREACH_DATA(j, data, length) {
|
||||||
|
@ -509,30 +530,36 @@ static int output_json(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == OUTPUT_JSON_PRETTY)
|
if (mode == OUTPUT_JSON_PRETTY)
|
||||||
fputs(",\n\t", stdout);
|
fputs(",\n\t", f);
|
||||||
else
|
else
|
||||||
fputs(", ", stdout);
|
fputs(", ", f);
|
||||||
|
|
||||||
json_escape(data, c - (const char*) data);
|
json_escape(f, data, c - (const char*) data, flags);
|
||||||
fputs(" : ", stdout);
|
fputs(" : ", f);
|
||||||
json_escape(c + 1, length - (c - (const char*) data) - 1);
|
json_escape(f, c + 1, length - (c - (const char*) data) - 1, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == OUTPUT_JSON_PRETTY)
|
if (mode == OUTPUT_JSON_PRETTY)
|
||||||
fputs("\n}\n", stdout);
|
fputs("\n}\n", f);
|
||||||
else
|
else
|
||||||
fputs(" }\n", stdout);
|
fputs(" }\n", f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int output_cat(sd_journal *j, OutputMode mode, unsigned line,
|
static int output_cat(
|
||||||
unsigned n_columns, OutputFlags flags) {
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
const void *data;
|
const void *data;
|
||||||
size_t l;
|
size_t l;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(j);
|
assert(j);
|
||||||
|
assert(f);
|
||||||
|
|
||||||
r = sd_journal_get_data(j, "MESSAGE", &data, &l);
|
r = sd_journal_get_data(j, "MESSAGE", &data, &l);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
@ -546,14 +573,19 @@ static int output_cat(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
|
|
||||||
assert(l >= 8);
|
assert(l >= 8);
|
||||||
|
|
||||||
fwrite((const char*) data + 8, 1, l - 8, stdout);
|
fwrite((const char*) data + 8, 1, l - 8, f);
|
||||||
putchar('\n');
|
fputc('\n', f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsigned line,
|
static int (*output_funcs[_OUTPUT_MODE_MAX])(
|
||||||
unsigned n_columns, OutputFlags flags) = {
|
FILE *f,
|
||||||
|
sd_journal*j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) = {
|
||||||
|
|
||||||
[OUTPUT_SHORT] = output_short,
|
[OUTPUT_SHORT] = output_short,
|
||||||
[OUTPUT_SHORT_MONOTONIC] = output_short,
|
[OUTPUT_SHORT_MONOTONIC] = output_short,
|
||||||
[OUTPUT_VERBOSE] = output_verbose,
|
[OUTPUT_VERBOSE] = output_verbose,
|
||||||
|
@ -563,8 +595,13 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsi
|
||||||
[OUTPUT_CAT] = output_cat
|
[OUTPUT_CAT] = output_cat
|
||||||
};
|
};
|
||||||
|
|
||||||
int output_journal(sd_journal *j, OutputMode mode, unsigned line,
|
int output_journal(
|
||||||
unsigned n_columns, OutputFlags flags) {
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags) {
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
assert(mode >= 0);
|
assert(mode >= 0);
|
||||||
assert(mode < _OUTPUT_MODE_MAX);
|
assert(mode < _OUTPUT_MODE_MAX);
|
||||||
|
@ -572,12 +609,13 @@ int output_journal(sd_journal *j, OutputMode mode, unsigned line,
|
||||||
if (n_columns <= 0)
|
if (n_columns <= 0)
|
||||||
n_columns = columns();
|
n_columns = columns();
|
||||||
|
|
||||||
ret = output_funcs[mode](j, mode, line, n_columns, flags);
|
ret = output_funcs[mode](f, j, mode, n_columns, flags);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int show_journal_by_unit(
|
int show_journal_by_unit(
|
||||||
|
FILE *f,
|
||||||
const char *unit,
|
const char *unit,
|
||||||
OutputMode mode,
|
OutputMode mode,
|
||||||
unsigned n_columns,
|
unsigned n_columns,
|
||||||
|
@ -585,7 +623,7 @@ int show_journal_by_unit(
|
||||||
unsigned how_many,
|
unsigned how_many,
|
||||||
OutputFlags flags) {
|
OutputFlags flags) {
|
||||||
|
|
||||||
char *m1 = NULL, *m2 = NULL, *m3 = NULL;
|
_cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL;
|
||||||
sd_journal *j = NULL;
|
sd_journal *j = NULL;
|
||||||
int r;
|
int r;
|
||||||
unsigned line = 0;
|
unsigned line = 0;
|
||||||
|
@ -652,11 +690,6 @@ int show_journal_by_unit(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (mode == OUTPUT_JSON) {
|
|
||||||
fputc('[', stdout);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
usec_t usec;
|
usec_t usec;
|
||||||
|
@ -688,7 +721,7 @@ int show_journal_by_unit(
|
||||||
|
|
||||||
line ++;
|
line ++;
|
||||||
|
|
||||||
r = output_journal(j, mode, line, n_columns, flags);
|
r = output_journal(f, j, mode, n_columns, flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -708,7 +741,7 @@ int show_journal_by_unit(
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (r > 0 && not_before < cutoff)
|
if (r > 0 && not_before < cutoff)
|
||||||
printf("Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
|
fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
|
||||||
|
|
||||||
warn_cutoff = false;
|
warn_cutoff = false;
|
||||||
}
|
}
|
||||||
|
@ -722,14 +755,7 @@ int show_journal_by_unit(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == OUTPUT_JSON)
|
|
||||||
fputs("\n]\n", stdout);
|
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
free(m1);
|
|
||||||
free(m2);
|
|
||||||
free(m3);
|
|
||||||
|
|
||||||
if (j)
|
if (j)
|
||||||
sd_journal_close(j);
|
sd_journal_close(j);
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,15 @@ typedef enum OutputFlags {
|
||||||
OUTPUT_COLOR = 1 << 4
|
OUTPUT_COLOR = 1 << 4
|
||||||
} OutputFlags;
|
} OutputFlags;
|
||||||
|
|
||||||
int output_journal(sd_journal *j, OutputMode mode, unsigned line,
|
int output_journal(
|
||||||
unsigned n_columns, OutputFlags flags);
|
FILE *f,
|
||||||
|
sd_journal *j,
|
||||||
|
OutputMode mode,
|
||||||
|
unsigned n_columns,
|
||||||
|
OutputFlags flags);
|
||||||
|
|
||||||
int show_journal_by_unit(
|
int show_journal_by_unit(
|
||||||
|
FILE *f,
|
||||||
const char *unit,
|
const char *unit,
|
||||||
OutputMode mode,
|
OutputMode mode,
|
||||||
unsigned n_columns,
|
unsigned n_columns,
|
||||||
|
|
|
@ -1688,7 +1688,8 @@ char *xescape(const char *s, const char *bad) {
|
||||||
* chars, in \xFF style escaping. May be reversed with
|
* chars, in \xFF style escaping. May be reversed with
|
||||||
* cunescape. */
|
* cunescape. */
|
||||||
|
|
||||||
if (!(r = new(char, strlen(s)*4+1)))
|
r = new(char, strlen(s) * 4 + 1);
|
||||||
|
if (!r)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (f = s, t = r; *f; f++) {
|
for (f = s, t = r; *f; f++) {
|
||||||
|
|
|
@ -2279,9 +2279,13 @@ static void print_status_info(UnitStatusInfo *i) {
|
||||||
on_tty() * OUTPUT_COLOR;
|
on_tty() * OUTPUT_COLOR;
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
show_journal_by_unit(i->id, arg_output, 0,
|
show_journal_by_unit(stdout,
|
||||||
|
i->id,
|
||||||
|
arg_output,
|
||||||
|
0,
|
||||||
i->inactive_exit_timestamp_monotonic,
|
i->inactive_exit_timestamp_monotonic,
|
||||||
arg_lines, flags);
|
arg_lines,
|
||||||
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->need_daemon_reload)
|
if (i->need_daemon_reload)
|
||||||
|
|
Loading…
Reference in a new issue