1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "logs-show.h"
33 #define PRINT_THRESHOLD 128
35 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
48 if (memcmp(data, field, fl))
56 memcpy(buf, (const char*) data + fl, nl);
66 static bool shall_print(bool show_all, char *p, size_t l) {
70 if (l > PRINT_THRESHOLD)
73 if (!utf8_is_printable_n(p, l))
79 static int output_short(sd_journal *j, unsigned line, unsigned n_columns,
85 char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL;
86 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;
90 SD_JOURNAL_FOREACH_DATA(j, data, length) {
92 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
98 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
104 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
110 r = parse_field(data, length, "_PID=", &pid, &pid_len);
116 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
122 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
128 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
134 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
144 if (flags & OUTPUT_MONOTONIC_MODE) {
151 r = safe_atou64(monotonic, &t);
154 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
157 log_error("Failed to get monotonic: %s", strerror(-r));
161 printf("[%5llu.%06llu]",
162 (unsigned long long) (t / USEC_PER_SEC),
163 (unsigned long long) (t % USEC_PER_SEC));
165 n += 1 + 5 + 1 + 6 + 1;
176 r = safe_atou64(realtime, &x);
179 r = sd_journal_get_realtime_usec(j, &x);
182 log_error("Failed to get realtime: %s", strerror(-r));
186 t = (time_t) (x / USEC_PER_SEC);
187 if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
188 log_error("Failed to format time.");
196 if (hostname && shall_print(flags & OUTPUT_SHOW_ALL,
197 hostname, hostname_len)) {
198 printf(" %.*s", (int) hostname_len, hostname);
199 n += hostname_len + 1;
202 if (identifier && shall_print(flags & OUTPUT_SHOW_ALL,
203 identifier, identifier_len)) {
204 printf(" %.*s", (int) identifier_len, identifier);
205 n += identifier_len + 1;
206 } else if (comm && shall_print(flags & OUTPUT_SHOW_ALL,
208 printf(" %.*s", (int) comm_len, comm);
213 if (pid && shall_print(flags & OUTPUT_SHOW_ALL, pid, pid_len)) {
214 printf("[%.*s]", (int) pid_len, pid);
216 } else if (fake_pid && shall_print(flags & OUTPUT_SHOW_ALL,
217 fake_pid, fake_pid_len)) {
218 printf("[%.*s]", (int) fake_pid_len, fake_pid);
219 n += fake_pid_len + 2;
222 if (flags & OUTPUT_SHOW_ALL)
223 printf(": %.*s\n", (int) message_len, message);
224 else if (!utf8_is_printable_n(message, message_len)) {
225 char bytes[FORMAT_BYTES_MAX];
226 printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
227 } else if ((flags & OUTPUT_FULL_WIDTH) ||
228 (message_len + n < n_columns))
229 printf(": %.*s\n", (int) message_len, message);
230 else if (n < n_columns && n_columns - n - 2 >= 3) {
233 e = ellipsize_mem(message, message_len, n_columns - n - 2, 90);
236 printf(": %.*s\n", (int) message_len, message);
259 static int output_short_realtime(sd_journal *j, unsigned line,
260 unsigned n_columns, OutputFlags flags) {
261 return output_short(j, line, n_columns, flags & ~OUTPUT_MONOTONIC_MODE);
264 static int output_short_monotonic(sd_journal *j, unsigned line,
265 unsigned n_columns, OutputFlags flags) {
266 return output_short(j, line, n_columns, flags | OUTPUT_MONOTONIC_MODE);
269 static int output_verbose(sd_journal *j, unsigned line,
270 unsigned n_columns, OutputFlags flags) {
275 char ts[FORMAT_TIMESTAMP_MAX];
280 r = sd_journal_get_realtime_usec(j, &realtime);
282 log_error("Failed to get realtime timestamp: %s", strerror(-r));
286 r = sd_journal_get_cursor(j, &cursor);
288 log_error("Failed to get cursor: %s", strerror(-r));
293 format_timestamp(ts, sizeof(ts), realtime),
298 SD_JOURNAL_FOREACH_DATA(j, data, length) {
299 if (!(flags & OUTPUT_SHOW_ALL) && (length > PRINT_THRESHOLD ||
300 !utf8_is_printable_n(data, length))) {
302 char bytes[FORMAT_BYTES_MAX];
304 c = memchr(data, '=', length);
306 log_error("Invalid field.");
310 printf("\t%.*s=[%s blob data]\n",
311 (int) (c - (const char*) data),
313 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
315 printf("\t%.*s\n", (int) length, (const char*) data);
321 static int output_export(sd_journal *j, unsigned line,
322 unsigned n_columns, OutputFlags flags) {
326 usec_t realtime, monotonic;
333 r = sd_journal_get_realtime_usec(j, &realtime);
335 log_error("Failed to get realtime timestamp: %s", strerror(-r));
339 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
341 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
345 r = sd_journal_get_cursor(j, &cursor);
347 log_error("Failed to get cursor: %s", strerror(-r));
351 printf("__CURSOR=%s\n"
352 "__REALTIME_TIMESTAMP=%llu\n"
353 "__MONOTONIC_TIMESTAMP=%llu\n"
356 (unsigned long long) realtime,
357 (unsigned long long) monotonic,
358 sd_id128_to_string(boot_id, sid));
362 SD_JOURNAL_FOREACH_DATA(j, data, length) {
364 /* We already printed the boot id, from the data in
365 * the header, hence let's suppress it here */
367 memcmp(data, "_BOOT_ID=", 9) == 0)
370 if (!utf8_is_printable_n(data, length)) {
374 c = memchr(data, '=', length);
376 log_error("Invalid field.");
380 fwrite(data, c - (const char*) data, 1, stdout);
382 le64 = htole64(length - (c - (const char*) data) - 1);
383 fwrite(&le64, sizeof(le64), 1, stdout);
384 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout);
386 fwrite(data, length, 1, stdout);
396 static void json_escape(const char* p, size_t l) {
397 if (!utf8_is_printable_n(p, l)) {
398 bool not_first = false;
404 printf(", %u", (uint8_t) *p);
407 printf("%u", (uint8_t) *p);
419 if (*p == '"' || *p == '\\') {
433 static int output_json(sd_journal *j, unsigned line,
434 unsigned n_columns, OutputFlags flags) {
435 uint64_t realtime, monotonic;
445 r = sd_journal_get_realtime_usec(j, &realtime);
447 log_error("Failed to get realtime timestamp: %s", strerror(-r));
451 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
453 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
457 r = sd_journal_get_cursor(j, &cursor);
459 log_error("Failed to get cursor: %s", strerror(-r));
466 fputs(",\n", stdout);
469 "\t\"__CURSOR\" : \"%s\",\n"
470 "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
471 "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
472 "\t\"_BOOT_ID\" : \"%s\"",
474 (unsigned long long) realtime,
475 (unsigned long long) monotonic,
476 sd_id128_to_string(boot_id, sid));
480 SD_JOURNAL_FOREACH_DATA(j, data, length) {
483 /* We already printed the boot id, from the data in
484 * the header, hence let's suppress it here */
486 memcmp(data, "_BOOT_ID=", 9) == 0)
489 c = memchr(data, '=', length);
491 log_error("Invalid field.");
495 fputs(",\n\t", stdout);
496 json_escape(data, c - (const char*) data);
497 fputs(" : ", stdout);
498 json_escape(c + 1, length - (c - (const char*) data) - 1);
501 fputs("\n}", stdout);
507 static int output_cat(sd_journal *j, unsigned line,
508 unsigned n_columns, OutputFlags flags) {
515 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
517 log_error("Failed to get data: %s", strerror(-r));
523 fwrite((const char*) data + 8, 1, l - 8, stdout);
529 static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line,
530 unsigned n_columns, OutputFlags flags) = {
531 [OUTPUT_SHORT] = output_short_realtime,
532 [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic,
533 [OUTPUT_VERBOSE] = output_verbose,
534 [OUTPUT_EXPORT] = output_export,
535 [OUTPUT_JSON] = output_json,
536 [OUTPUT_CAT] = output_cat
539 int output_journal(sd_journal *j, OutputMode mode, unsigned line,
540 unsigned n_columns, OutputFlags flags) {
542 assert(mode < _OUTPUT_MODE_MAX);
545 n_columns = columns();
547 return output_funcs[mode](j, line, n_columns, flags);
550 int show_journal_by_unit(
559 sd_journal *j = NULL;
562 bool need_seek = false;
563 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
566 assert(mode < _OUTPUT_MODE_MAX);
569 if (!endswith(unit, ".service") &&
570 !endswith(unit, ".socket") &&
571 !endswith(unit, ".mount") &&
572 !endswith(unit, ".swap"))
578 if (asprintf(&m, "_SYSTEMD_UNIT=%s", unit) < 0) {
583 r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY);
587 r = sd_journal_add_match(j, m, strlen(m));
591 r = sd_journal_seek_tail(j);
595 r = sd_journal_previous_skip(j, how_many);
599 if (mode == OUTPUT_JSON) {
609 r = sd_journal_next(j);
619 if (not_before > 0) {
620 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
622 /* -ESTALE is returned if the
623 timestamp is not from this boot */
629 if (usec < not_before)
635 r = output_journal(j, mode, line, n_columns, flags);
640 if (warn_cutoff && line < how_many && not_before > 0) {
644 /* Check whether the cutoff line is too early */
646 r = sd_id128_get_boot(&boot_id);
650 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
654 if (r > 0 && not_before < cutoff)
655 printf("Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
660 if (!(flags & OUTPUT_FOLLOW))
663 r = sd_journal_wait(j, (usec_t) -1);
669 if (mode == OUTPUT_JSON)
670 fputs("\n]\n", stdout);
682 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
683 [OUTPUT_SHORT] = "short",
684 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
685 [OUTPUT_VERBOSE] = "verbose",
686 [OUTPUT_EXPORT] = "export",
687 [OUTPUT_JSON] = "json",
691 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);