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/>.
29 #include "logs-show.h"
35 #include "journal-internal.h"
37 /* up to three lines (each up to 100 characters),
38 or 300 characters, whichever is less */
39 #define PRINT_LINE_THRESHOLD 3
40 #define PRINT_CHAR_THRESHOLD 300
42 #define JSON_THRESHOLD 4096
44 static int print_catalog(FILE *f, sd_journal *j) {
46 _cleanup_free_ char *t = NULL, *z = NULL;
49 r = sd_journal_get_catalog(j, &t);
53 z = strreplace(strstrip(t), "\n", "\n-- ");
64 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
77 if (memcmp(data, field, fl))
85 memcpy(buf, (const char*) data + fl, nl);
95 static bool shall_print(const char *p, size_t l, OutputFlags flags) {
98 if (flags & OUTPUT_SHOW_ALL)
101 if (l >= PRINT_CHAR_THRESHOLD)
104 if (!utf8_is_printable(p, l))
110 static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
111 const char *color_on = "", *color_off = "";
112 const char *pos, *end;
113 bool ellipsized = false;
116 if (flags & OUTPUT_COLOR) {
117 if (priority <= LOG_ERR) {
118 color_on = ANSI_HIGHLIGHT_RED_ON;
119 color_off = ANSI_HIGHLIGHT_OFF;
120 } else if (priority <= LOG_NOTICE) {
121 color_on = ANSI_HIGHLIGHT_ON;
122 color_off = ANSI_HIGHLIGHT_OFF;
127 pos < message + message_len;
128 pos = end + 1, line++) {
129 bool continuation = line > 0;
132 for (end = pos; end < message + message_len && *end != '\n'; end++)
137 /* We need to figure out when we are showing not-last line, *and*
138 * will skip subsequent lines. In that case, we will put the dots
139 * at the end of the line, instead of putting dots in the middle
143 line + 1 == PRINT_LINE_THRESHOLD ||
144 end + 1 >= message + PRINT_CHAR_THRESHOLD;
146 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
147 (prefix + len + 1 < n_columns && !tail_line)) {
148 fprintf(f, "%*s%s%.*s%s\n",
149 continuation * prefix, "",
150 color_on, len, pos, color_off);
154 /* Beyond this point, ellipsization will happen. */
157 if (prefix < n_columns && n_columns - prefix >= 3) {
158 if (n_columns - prefix > (unsigned) len + 3)
159 fprintf(f, "%*s%s%.*s...%s\n",
160 continuation * prefix, "",
161 color_on, len, pos, color_off);
163 _cleanup_free_ char *e;
165 e = ellipsize_mem(pos, len, n_columns - prefix,
166 tail_line ? 100 : 90);
168 fprintf(f, "%*s%s%.*s%s\n",
169 continuation * prefix, "",
170 color_on, len, pos, color_off);
172 fprintf(f, "%*s%s%s%s\n",
173 continuation * prefix, "",
174 color_on, e, color_off);
186 static int output_short(
197 _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
198 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;
200 bool ellipsized = false;
205 /* Set the threshold to one bigger than the actual print
206 * threshold, so that if the line is actually longer than what
207 * we're willing to print, ellipsization will occur. This way
208 * we won't output a misleading line without any indication of
211 sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
213 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
215 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
221 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
227 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
233 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
239 r = parse_field(data, length, "_PID=", &pid, &pid_len);
245 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
251 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
257 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
263 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
274 if (!(flags & OUTPUT_SHOW_ALL))
275 strip_tab_ansi(&message, &message_len);
277 if (priority_len == 1 && *priority >= '0' && *priority <= '7')
280 if (mode == OUTPUT_SHORT_MONOTONIC) {
287 r = safe_atou64(monotonic, &t);
290 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
293 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
297 fprintf(f, "[%5llu.%06llu]",
298 (unsigned long long) (t / USEC_PER_SEC),
299 (unsigned long long) (t % USEC_PER_SEC));
301 n += 1 + 5 + 1 + 6 + 1;
312 r = safe_atou64(realtime, &x);
315 r = sd_journal_get_realtime_usec(j, &x);
318 log_error("Failed to get realtime timestamp: %s", strerror(-r));
322 t = (time_t) (x / USEC_PER_SEC);
325 case OUTPUT_SHORT_ISO:
326 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", localtime_r(&t, &tm));
328 case OUTPUT_SHORT_PRECISE:
329 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
331 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
332 ".%06llu", x % USEC_PER_SEC);
336 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
340 log_error("Failed to format time.");
348 if (hostname && shall_print(hostname, hostname_len, flags)) {
349 fprintf(f, " %.*s", (int) hostname_len, hostname);
350 n += hostname_len + 1;
353 if (identifier && shall_print(identifier, identifier_len, flags)) {
354 fprintf(f, " %.*s", (int) identifier_len, identifier);
355 n += identifier_len + 1;
356 } else if (comm && shall_print(comm, comm_len, flags)) {
357 fprintf(f, " %.*s", (int) comm_len, comm);
362 if (pid && shall_print(pid, pid_len, flags)) {
363 fprintf(f, "[%.*s]", (int) pid_len, pid);
365 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
366 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
367 n += fake_pid_len + 2;
370 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
371 char bytes[FORMAT_BYTES_MAX];
372 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
376 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
379 if (flags & OUTPUT_CATALOG)
385 static int output_verbose(
394 _cleanup_free_ char *cursor = NULL;
396 char ts[FORMAT_TIMESTAMP_MAX + 7];
402 sd_journal_set_data_threshold(j, 0);
404 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
406 log_debug("Source realtime timestamp not found");
408 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
409 "Failed to get source realtime timestamp: %s", strerror(-r));
412 _cleanup_free_ char *value = NULL;
415 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
417 log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
419 r = safe_atou64(value, &realtime);
421 log_debug("Failed to parse realtime timestamp: %s",
427 r = sd_journal_get_realtime_usec(j, &realtime);
429 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
430 "Failed to get realtime timestamp: %s", strerror(-r));
435 r = sd_journal_get_cursor(j, &cursor);
437 log_error("Failed to get cursor: %s", strerror(-r));
441 fprintf(f, "%s [%s]\n",
442 format_timestamp_us(ts, sizeof(ts), realtime),
445 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
448 const char *on = "", *off = "";
450 c = memchr(data, '=', length);
452 log_error("Invalid field.");
455 fieldlen = c - (const char*) data;
457 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
458 on = ANSI_HIGHLIGHT_ON;
459 off = ANSI_HIGHLIGHT_OFF;
462 if (flags & OUTPUT_SHOW_ALL ||
463 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
464 && utf8_is_printable(data, length))) {
465 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
466 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
469 char bytes[FORMAT_BYTES_MAX];
471 fprintf(f, " %s%.*s=[%s blob data]%s\n",
473 (int) (c - (const char*) data),
475 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
483 if (flags & OUTPUT_CATALOG)
489 static int output_export(
499 usec_t realtime, monotonic;
500 _cleanup_free_ char *cursor = NULL;
506 sd_journal_set_data_threshold(j, 0);
508 r = sd_journal_get_realtime_usec(j, &realtime);
510 log_error("Failed to get realtime timestamp: %s", strerror(-r));
514 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
516 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
520 r = sd_journal_get_cursor(j, &cursor);
522 log_error("Failed to get cursor: %s", strerror(-r));
528 "__REALTIME_TIMESTAMP=%llu\n"
529 "__MONOTONIC_TIMESTAMP=%llu\n"
532 (unsigned long long) realtime,
533 (unsigned long long) monotonic,
534 sd_id128_to_string(boot_id, sid));
536 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
538 /* We already printed the boot id, from the data in
539 * the header, hence let's suppress it here */
541 startswith(data, "_BOOT_ID="))
544 if (!utf8_is_printable(data, length)) {
548 c = memchr(data, '=', length);
550 log_error("Invalid field.");
554 fwrite(data, c - (const char*) data, 1, f);
556 le64 = htole64(length - (c - (const char*) data) - 1);
557 fwrite(&le64, sizeof(le64), 1, f);
558 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
560 fwrite(data, length, 1, f);
582 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
586 else if (!utf8_is_printable(p, l)) {
587 bool not_first = false;
593 fprintf(f, ", %u", (uint8_t) *p);
596 fprintf(f, "%u", (uint8_t) *p);
608 if (*p == '"' || *p == '\\') {
611 } else if (*p == '\n')
614 fprintf(f, "\\u%04x", *p);
626 static int output_json(
633 uint64_t realtime, monotonic;
634 _cleanup_free_ char *cursor = NULL;
641 bool done, separator;
645 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
647 r = sd_journal_get_realtime_usec(j, &realtime);
649 log_error("Failed to get realtime timestamp: %s", strerror(-r));
653 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
655 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
659 r = sd_journal_get_cursor(j, &cursor);
661 log_error("Failed to get cursor: %s", strerror(-r));
665 if (mode == OUTPUT_JSON_PRETTY)
668 "\t\"__CURSOR\" : \"%s\",\n"
669 "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
670 "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
671 "\t\"_BOOT_ID\" : \"%s\"",
673 (unsigned long long) realtime,
674 (unsigned long long) monotonic,
675 sd_id128_to_string(boot_id, sid));
677 if (mode == OUTPUT_JSON_SSE)
681 "{ \"__CURSOR\" : \"%s\", "
682 "\"__REALTIME_TIMESTAMP\" : \"%llu\", "
683 "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
684 "\"_BOOT_ID\" : \"%s\"",
686 (unsigned long long) realtime,
687 (unsigned long long) monotonic,
688 sd_id128_to_string(boot_id, sid));
691 h = hashmap_new(string_hash_func, string_compare_func);
695 /* First round, iterate through the entry and count how often each field appears */
696 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
702 memcmp(data, "_BOOT_ID=", 9) == 0)
705 eq = memchr(data, '=', length);
709 n = strndup(data, eq - (const char*) data);
715 u = PTR_TO_UINT(hashmap_get(h, n));
717 r = hashmap_put(h, n, UINT_TO_PTR(1));
723 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
737 SD_JOURNAL_FOREACH_DATA(j, data, length) {
743 /* We already printed the boot id, from the data in
744 * the header, hence let's suppress it here */
746 memcmp(data, "_BOOT_ID=", 9) == 0)
749 eq = memchr(data, '=', length);
754 if (mode == OUTPUT_JSON_PRETTY)
760 m = eq - (const char*) data;
762 n = strndup(data, m);
768 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
770 /* We already printed this, let's jump to the next */
776 /* Field only appears once, output it directly */
778 json_escape(f, data, m, flags);
781 json_escape(f, eq + 1, length - m - 1, flags);
783 hashmap_remove(h, n);
792 /* Field appears multiple times, output it as array */
793 json_escape(f, data, m, flags);
795 json_escape(f, eq + 1, length - m - 1, flags);
797 /* Iterate through the end of the list */
799 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
803 if (memcmp(data, n, m) != 0)
806 if (((const char*) data)[m] != '=')
810 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
815 hashmap_remove(h, n);
819 /* Iterate data fields form the beginning */
829 if (mode == OUTPUT_JSON_PRETTY)
831 else if (mode == OUTPUT_JSON_SSE)
839 while ((k = hashmap_steal_first_key(h)))
847 static int output_cat(
861 sd_journal_set_data_threshold(j, 0);
863 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
865 /* An entry without MESSAGE=? */
869 log_error("Failed to get data: %s", strerror(-r));
875 fwrite((const char*) data + 8, 1, l - 8, f);
881 static int (*output_funcs[_OUTPUT_MODE_MAX])(
886 OutputFlags flags) = {
888 [OUTPUT_SHORT] = output_short,
889 [OUTPUT_SHORT_ISO] = output_short,
890 [OUTPUT_SHORT_PRECISE] = output_short,
891 [OUTPUT_SHORT_MONOTONIC] = output_short,
892 [OUTPUT_VERBOSE] = output_verbose,
893 [OUTPUT_EXPORT] = output_export,
894 [OUTPUT_JSON] = output_json,
895 [OUTPUT_JSON_PRETTY] = output_json,
896 [OUTPUT_JSON_SSE] = output_json,
897 [OUTPUT_CAT] = output_cat
910 assert(mode < _OUTPUT_MODE_MAX);
913 n_columns = columns();
915 ret = output_funcs[mode](f, j, mode, n_columns, flags);
918 if (ellipsized && ret > 0)
924 static int show_journal(FILE *f,
935 bool need_seek = false;
936 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
940 assert(mode < _OUTPUT_MODE_MAX);
943 r = sd_journal_seek_tail(j);
947 r = sd_journal_previous_skip(j, how_many);
956 r = sd_journal_next(j);
966 if (not_before > 0) {
967 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
969 /* -ESTALE is returned if the
970 timestamp is not from this boot */
976 if (usec < not_before)
982 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
987 if (warn_cutoff && line < how_many && not_before > 0) {
991 /* Check whether the cutoff line is too early */
993 r = sd_id128_get_boot(&boot_id);
997 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1001 if (r > 0 && not_before < cutoff)
1002 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1004 warn_cutoff = false;
1007 if (!(flags & OUTPUT_FOLLOW))
1010 r = sd_journal_wait(j, (usec_t) -1);
1020 int add_matches_for_unit(sd_journal *j, const char *unit) {
1022 char *m1, *m2, *m3, *m4;
1027 m1 = strappenda("_SYSTEMD_UNIT=", unit);
1028 m2 = strappenda("COREDUMP_UNIT=", unit);
1029 m3 = strappenda("UNIT=", unit);
1030 m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1033 /* Look for messages from the service itself */
1034 (r = sd_journal_add_match(j, m1, 0)) ||
1036 /* Look for coredumps of the service */
1037 (r = sd_journal_add_disjunction(j)) ||
1038 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1039 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1040 (r = sd_journal_add_match(j, m2, 0)) ||
1042 /* Look for messages from PID 1 about this service */
1043 (r = sd_journal_add_disjunction(j)) ||
1044 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1045 (r = sd_journal_add_match(j, m3, 0)) ||
1047 /* Look for messages from authorized daemons about this service */
1048 (r = sd_journal_add_disjunction(j)) ||
1049 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1050 (r = sd_journal_add_match(j, m4, 0))
1053 if (r == 0 && endswith(unit, ".slice")) {
1054 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1056 /* Show all messages belonging to a slice */
1058 (r = sd_journal_add_disjunction(j)) ||
1059 (r = sd_journal_add_match(j, m5, 0))
1066 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1068 char *m1, *m2, *m3, *m4;
1069 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1074 m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1075 m2 = strappenda("USER_UNIT=", unit);
1076 m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1077 m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1078 sprintf(muid, "_UID=%lu", (unsigned long) uid);
1081 /* Look for messages from the user service itself */
1082 (r = sd_journal_add_match(j, m1, 0)) ||
1083 (r = sd_journal_add_match(j, muid, 0)) ||
1085 /* Look for messages from systemd about this service */
1086 (r = sd_journal_add_disjunction(j)) ||
1087 (r = sd_journal_add_match(j, m2, 0)) ||
1088 (r = sd_journal_add_match(j, muid, 0)) ||
1090 /* Look for coredumps of the service */
1091 (r = sd_journal_add_disjunction(j)) ||
1092 (r = sd_journal_add_match(j, m3, 0)) ||
1093 (r = sd_journal_add_match(j, muid, 0)) ||
1094 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1096 /* Look for messages from authorized daemons about this service */
1097 (r = sd_journal_add_disjunction(j)) ||
1098 (r = sd_journal_add_match(j, m4, 0)) ||
1099 (r = sd_journal_add_match(j, muid, 0)) ||
1100 (r = sd_journal_add_match(j, "_UID=0", 0))
1103 if (r == 0 && endswith(unit, ".slice")) {
1104 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1106 /* Show all messages belonging to a slice */
1108 (r = sd_journal_add_disjunction(j)) ||
1109 (r = sd_journal_add_match(j, m5, 0)) ||
1110 (r = sd_journal_add_match(j, muid, 0))
1117 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1118 _cleanup_free_ char *leader = NULL, *class = NULL;
1119 _cleanup_close_pipe_ int sock[2] = { -1, -1 };
1120 _cleanup_close_ int nsfd = -1;
1131 if (!filename_is_safe(machine))
1134 p = strappenda("/run/systemd/machines/", machine);
1136 r = parse_env_file(p, NEWLINE, "LEADER", &leader, "CLASS", &class, NULL);
1141 if (!streq_ptr(class, "container"))
1143 r = parse_pid(leader, &pid);
1147 ns = procfs_file_alloca(pid, "ns/mnt");
1149 nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1153 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sock) < 0)
1163 close_nointr_nofail(sock[0]);
1166 r = setns(nsfd, CLONE_NEWNS);
1168 _exit(EXIT_FAILURE);
1170 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1172 _exit(EXIT_FAILURE);
1174 k = loop_read(fd, buf, 36, false);
1175 close_nointr_nofail(fd);
1177 _exit(EXIT_FAILURE);
1179 k = send(sock[1], buf, 36, MSG_NOSIGNAL);
1181 _exit(EXIT_FAILURE);
1183 _exit(EXIT_SUCCESS);
1186 close_nointr_nofail(sock[1]);
1189 k = recv(sock[0], buf, 36, 0);
1193 r = wait_for_terminate(child, &si);
1194 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1195 return r < 0 ? r : -EIO;
1198 r = sd_id128_from_string(buf, boot_id);
1205 int add_match_this_boot(sd_journal *j, const char *machine) {
1206 char match[9+32+1] = "_BOOT_ID=";
1213 r = get_boot_id_for_machine(machine, &boot_id);
1215 log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1219 r = sd_id128_get_boot(&boot_id);
1221 log_error("Failed to get boot id: %s", strerror(-r));
1226 sd_id128_to_string(boot_id, match + 9);
1227 r = sd_journal_add_match(j, match, strlen(match));
1229 log_error("Failed to add match: %s", strerror(-r));
1233 r = sd_journal_add_conjunction(j);
1240 int show_journal_by_unit(
1252 _cleanup_journal_close_ sd_journal*j = NULL;
1254 int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1257 assert(mode < _OUTPUT_MODE_MAX);
1263 r = sd_journal_open(&j, jflags);
1267 r = add_match_this_boot(j, NULL);
1272 r = add_matches_for_unit(j, unit);
1274 r = add_matches_for_user_unit(j, unit, uid);
1278 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1279 _cleanup_free_ char *filter;
1281 filter = journal_make_match_string(j);
1282 log_debug("Journal filter: %s", filter);
1285 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1288 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1289 [OUTPUT_SHORT] = "short",
1290 [OUTPUT_SHORT_ISO] = "short-iso",
1291 [OUTPUT_SHORT_PRECISE] = "short-precise",
1292 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1293 [OUTPUT_VERBOSE] = "verbose",
1294 [OUTPUT_EXPORT] = "export",
1295 [OUTPUT_JSON] = "json",
1296 [OUTPUT_JSON_PRETTY] = "json-pretty",
1297 [OUTPUT_JSON_SSE] = "json-sse",
1298 [OUTPUT_CAT] = "cat"
1301 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);