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/>.
26 #include <sys/socket.h>
30 #include "logs-show.h"
36 #include "journal-internal.h"
38 /* up to three lines (each up to 100 characters),
39 or 300 characters, whichever is less */
40 #define PRINT_LINE_THRESHOLD 3
41 #define PRINT_CHAR_THRESHOLD 300
43 #define JSON_THRESHOLD 4096
45 static int print_catalog(FILE *f, sd_journal *j) {
47 _cleanup_free_ char *t = NULL, *z = NULL;
50 r = sd_journal_get_catalog(j, &t);
54 z = strreplace(strstrip(t), "\n", "\n-- ");
65 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
78 if (memcmp(data, field, fl))
86 memcpy(buf, (const char*) data + fl, nl);
96 static bool shall_print(const char *p, size_t l, OutputFlags flags) {
99 if (flags & OUTPUT_SHOW_ALL)
102 if (l >= PRINT_CHAR_THRESHOLD)
105 if (!utf8_is_printable(p, l))
111 static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
112 const char *color_on = "", *color_off = "";
113 const char *pos, *end;
114 bool ellipsized = false;
117 if (flags & OUTPUT_COLOR) {
118 if (priority <= LOG_ERR) {
119 color_on = ANSI_HIGHLIGHT_RED_ON;
120 color_off = ANSI_HIGHLIGHT_OFF;
121 } else if (priority <= LOG_NOTICE) {
122 color_on = ANSI_HIGHLIGHT_ON;
123 color_off = ANSI_HIGHLIGHT_OFF;
128 pos < message + message_len;
129 pos = end + 1, line++) {
130 bool continuation = line > 0;
133 for (end = pos; end < message + message_len && *end != '\n'; end++)
138 /* We need to figure out when we are showing not-last line, *and*
139 * will skip subsequent lines. In that case, we will put the dots
140 * at the end of the line, instead of putting dots in the middle
144 line + 1 == PRINT_LINE_THRESHOLD ||
145 end + 1 >= message + PRINT_CHAR_THRESHOLD;
147 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
148 (prefix + len + 1 < n_columns && !tail_line)) {
149 fprintf(f, "%*s%s%.*s%s\n",
150 continuation * prefix, "",
151 color_on, len, pos, color_off);
155 /* Beyond this point, ellipsization will happen. */
158 if (prefix < n_columns && n_columns - prefix >= 3) {
159 if (n_columns - prefix > (unsigned) len + 3)
160 fprintf(f, "%*s%s%.*s...%s\n",
161 continuation * prefix, "",
162 color_on, len, pos, color_off);
164 _cleanup_free_ char *e;
166 e = ellipsize_mem(pos, len, n_columns - prefix,
167 tail_line ? 100 : 90);
169 fprintf(f, "%*s%s%.*s%s\n",
170 continuation * prefix, "",
171 color_on, len, pos, color_off);
173 fprintf(f, "%*s%s%s%s\n",
174 continuation * prefix, "",
175 color_on, e, color_off);
187 static int output_short(
198 _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
199 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;
201 bool ellipsized = false;
206 /* Set the threshold to one bigger than the actual print
207 * threshold, so that if the line is actually longer than what
208 * we're willing to print, ellipsization will occur. This way
209 * we won't output a misleading line without any indication of
212 sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
214 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
216 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
222 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
228 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
234 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
240 r = parse_field(data, length, "_PID=", &pid, &pid_len);
246 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
252 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
258 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
264 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
275 if (!(flags & OUTPUT_SHOW_ALL))
276 strip_tab_ansi(&message, &message_len);
278 if (priority_len == 1 && *priority >= '0' && *priority <= '7')
281 if (mode == OUTPUT_SHORT_MONOTONIC) {
288 r = safe_atou64(monotonic, &t);
291 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
294 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
298 fprintf(f, "[%5llu.%06llu]",
299 (unsigned long long) (t / USEC_PER_SEC),
300 (unsigned long long) (t % USEC_PER_SEC));
302 n += 1 + 5 + 1 + 6 + 1;
313 r = safe_atou64(realtime, &x);
316 r = sd_journal_get_realtime_usec(j, &x);
319 log_error("Failed to get realtime timestamp: %s", strerror(-r));
323 t = (time_t) (x / USEC_PER_SEC);
326 case OUTPUT_SHORT_ISO:
327 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", localtime_r(&t, &tm));
329 case OUTPUT_SHORT_PRECISE:
330 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
332 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
333 ".%06llu", x % USEC_PER_SEC);
337 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
341 log_error("Failed to format time.");
349 if (hostname && shall_print(hostname, hostname_len, flags)) {
350 fprintf(f, " %.*s", (int) hostname_len, hostname);
351 n += hostname_len + 1;
354 if (identifier && shall_print(identifier, identifier_len, flags)) {
355 fprintf(f, " %.*s", (int) identifier_len, identifier);
356 n += identifier_len + 1;
357 } else if (comm && shall_print(comm, comm_len, flags)) {
358 fprintf(f, " %.*s", (int) comm_len, comm);
363 if (pid && shall_print(pid, pid_len, flags)) {
364 fprintf(f, "[%.*s]", (int) pid_len, pid);
366 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
367 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
368 n += fake_pid_len + 2;
371 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
372 char bytes[FORMAT_BYTES_MAX];
373 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
377 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
380 if (flags & OUTPUT_CATALOG)
386 static int output_verbose(
395 _cleanup_free_ char *cursor = NULL;
397 char ts[FORMAT_TIMESTAMP_MAX + 7];
403 sd_journal_set_data_threshold(j, 0);
405 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
407 log_debug("Source realtime timestamp not found");
409 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
410 "Failed to get source realtime timestamp: %s", strerror(-r));
413 _cleanup_free_ char *value = NULL;
416 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
418 log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
420 r = safe_atou64(value, &realtime);
422 log_debug("Failed to parse realtime timestamp: %s",
428 r = sd_journal_get_realtime_usec(j, &realtime);
430 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
431 "Failed to get realtime timestamp: %s", strerror(-r));
436 r = sd_journal_get_cursor(j, &cursor);
438 log_error("Failed to get cursor: %s", strerror(-r));
442 fprintf(f, "%s [%s]\n",
443 format_timestamp_us(ts, sizeof(ts), realtime),
446 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
449 const char *on = "", *off = "";
451 c = memchr(data, '=', length);
453 log_error("Invalid field.");
456 fieldlen = c - (const char*) data;
458 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
459 on = ANSI_HIGHLIGHT_ON;
460 off = ANSI_HIGHLIGHT_OFF;
463 if (flags & OUTPUT_SHOW_ALL ||
464 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
465 && utf8_is_printable(data, length))) {
466 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
467 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
470 char bytes[FORMAT_BYTES_MAX];
472 fprintf(f, " %s%.*s=[%s blob data]%s\n",
474 (int) (c - (const char*) data),
476 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
484 if (flags & OUTPUT_CATALOG)
490 static int output_export(
500 usec_t realtime, monotonic;
501 _cleanup_free_ char *cursor = NULL;
507 sd_journal_set_data_threshold(j, 0);
509 r = sd_journal_get_realtime_usec(j, &realtime);
511 log_error("Failed to get realtime timestamp: %s", strerror(-r));
515 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
517 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
521 r = sd_journal_get_cursor(j, &cursor);
523 log_error("Failed to get cursor: %s", strerror(-r));
529 "__REALTIME_TIMESTAMP=%llu\n"
530 "__MONOTONIC_TIMESTAMP=%llu\n"
533 (unsigned long long) realtime,
534 (unsigned long long) monotonic,
535 sd_id128_to_string(boot_id, sid));
537 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
539 /* We already printed the boot id, from the data in
540 * the header, hence let's suppress it here */
542 startswith(data, "_BOOT_ID="))
545 if (!utf8_is_printable(data, length)) {
549 c = memchr(data, '=', length);
551 log_error("Invalid field.");
555 fwrite(data, c - (const char*) data, 1, f);
557 le64 = htole64(length - (c - (const char*) data) - 1);
558 fwrite(&le64, sizeof(le64), 1, f);
559 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
561 fwrite(data, length, 1, f);
583 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
587 else if (!utf8_is_printable(p, l)) {
588 bool not_first = false;
594 fprintf(f, ", %u", (uint8_t) *p);
597 fprintf(f, "%u", (uint8_t) *p);
609 if (*p == '"' || *p == '\\') {
612 } else if (*p == '\n')
615 fprintf(f, "\\u%04x", *p);
627 static int output_json(
634 uint64_t realtime, monotonic;
635 _cleanup_free_ char *cursor = NULL;
642 bool done, separator;
646 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
648 r = sd_journal_get_realtime_usec(j, &realtime);
650 log_error("Failed to get realtime timestamp: %s", strerror(-r));
654 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
656 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
660 r = sd_journal_get_cursor(j, &cursor);
662 log_error("Failed to get cursor: %s", strerror(-r));
666 if (mode == OUTPUT_JSON_PRETTY)
669 "\t\"__CURSOR\" : \"%s\",\n"
670 "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
671 "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
672 "\t\"_BOOT_ID\" : \"%s\"",
674 (unsigned long long) realtime,
675 (unsigned long long) monotonic,
676 sd_id128_to_string(boot_id, sid));
678 if (mode == OUTPUT_JSON_SSE)
682 "{ \"__CURSOR\" : \"%s\", "
683 "\"__REALTIME_TIMESTAMP\" : \"%llu\", "
684 "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
685 "\"_BOOT_ID\" : \"%s\"",
687 (unsigned long long) realtime,
688 (unsigned long long) monotonic,
689 sd_id128_to_string(boot_id, sid));
692 h = hashmap_new(string_hash_func, string_compare_func);
696 /* First round, iterate through the entry and count how often each field appears */
697 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
703 memcmp(data, "_BOOT_ID=", 9) == 0)
706 eq = memchr(data, '=', length);
710 n = strndup(data, eq - (const char*) data);
716 u = PTR_TO_UINT(hashmap_get(h, n));
718 r = hashmap_put(h, n, UINT_TO_PTR(1));
724 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
738 SD_JOURNAL_FOREACH_DATA(j, data, length) {
744 /* We already printed the boot id, from the data in
745 * the header, hence let's suppress it here */
747 memcmp(data, "_BOOT_ID=", 9) == 0)
750 eq = memchr(data, '=', length);
755 if (mode == OUTPUT_JSON_PRETTY)
761 m = eq - (const char*) data;
763 n = strndup(data, m);
769 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
771 /* We already printed this, let's jump to the next */
777 /* Field only appears once, output it directly */
779 json_escape(f, data, m, flags);
782 json_escape(f, eq + 1, length - m - 1, flags);
784 hashmap_remove(h, n);
793 /* Field appears multiple times, output it as array */
794 json_escape(f, data, m, flags);
796 json_escape(f, eq + 1, length - m - 1, flags);
798 /* Iterate through the end of the list */
800 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
804 if (memcmp(data, n, m) != 0)
807 if (((const char*) data)[m] != '=')
811 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
816 hashmap_remove(h, n);
820 /* Iterate data fields form the beginning */
830 if (mode == OUTPUT_JSON_PRETTY)
832 else if (mode == OUTPUT_JSON_SSE)
840 while ((k = hashmap_steal_first_key(h)))
848 static int output_cat(
862 sd_journal_set_data_threshold(j, 0);
864 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
866 /* An entry without MESSAGE=? */
870 log_error("Failed to get data: %s", strerror(-r));
876 fwrite((const char*) data + 8, 1, l - 8, f);
882 static int (*output_funcs[_OUTPUT_MODE_MAX])(
887 OutputFlags flags) = {
889 [OUTPUT_SHORT] = output_short,
890 [OUTPUT_SHORT_ISO] = output_short,
891 [OUTPUT_SHORT_PRECISE] = output_short,
892 [OUTPUT_SHORT_MONOTONIC] = output_short,
893 [OUTPUT_VERBOSE] = output_verbose,
894 [OUTPUT_EXPORT] = output_export,
895 [OUTPUT_JSON] = output_json,
896 [OUTPUT_JSON_PRETTY] = output_json,
897 [OUTPUT_JSON_SSE] = output_json,
898 [OUTPUT_CAT] = output_cat
911 assert(mode < _OUTPUT_MODE_MAX);
914 n_columns = columns();
916 ret = output_funcs[mode](f, j, mode, n_columns, flags);
919 if (ellipsized && ret > 0)
925 static int show_journal(FILE *f,
936 bool need_seek = false;
937 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
941 assert(mode < _OUTPUT_MODE_MAX);
944 r = sd_journal_seek_tail(j);
948 r = sd_journal_previous_skip(j, how_many);
957 r = sd_journal_next(j);
967 if (not_before > 0) {
968 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
970 /* -ESTALE is returned if the
971 timestamp is not from this boot */
977 if (usec < not_before)
983 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
988 if (warn_cutoff && line < how_many && not_before > 0) {
992 /* Check whether the cutoff line is too early */
994 r = sd_id128_get_boot(&boot_id);
998 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1002 if (r > 0 && not_before < cutoff)
1003 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1005 warn_cutoff = false;
1008 if (!(flags & OUTPUT_FOLLOW))
1011 r = sd_journal_wait(j, (usec_t) -1);
1021 int add_matches_for_unit(sd_journal *j, const char *unit) {
1023 char *m1, *m2, *m3, *m4;
1028 m1 = strappenda("_SYSTEMD_UNIT=", unit);
1029 m2 = strappenda("COREDUMP_UNIT=", unit);
1030 m3 = strappenda("UNIT=", unit);
1031 m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1034 /* Look for messages from the service itself */
1035 (r = sd_journal_add_match(j, m1, 0)) ||
1037 /* Look for coredumps of the service */
1038 (r = sd_journal_add_disjunction(j)) ||
1039 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1040 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1041 (r = sd_journal_add_match(j, m2, 0)) ||
1043 /* Look for messages from PID 1 about this service */
1044 (r = sd_journal_add_disjunction(j)) ||
1045 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1046 (r = sd_journal_add_match(j, m3, 0)) ||
1048 /* Look for messages from authorized daemons about this service */
1049 (r = sd_journal_add_disjunction(j)) ||
1050 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1051 (r = sd_journal_add_match(j, m4, 0))
1054 if (r == 0 && endswith(unit, ".slice")) {
1055 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1057 /* Show all messages belonging to a slice */
1059 (r = sd_journal_add_disjunction(j)) ||
1060 (r = sd_journal_add_match(j, m5, 0))
1067 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1069 char *m1, *m2, *m3, *m4;
1070 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1075 m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1076 m2 = strappenda("USER_UNIT=", unit);
1077 m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1078 m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1079 sprintf(muid, "_UID=%lu", (unsigned long) uid);
1082 /* Look for messages from the user service itself */
1083 (r = sd_journal_add_match(j, m1, 0)) ||
1084 (r = sd_journal_add_match(j, muid, 0)) ||
1086 /* Look for messages from systemd about this service */
1087 (r = sd_journal_add_disjunction(j)) ||
1088 (r = sd_journal_add_match(j, m2, 0)) ||
1089 (r = sd_journal_add_match(j, muid, 0)) ||
1091 /* Look for coredumps of the service */
1092 (r = sd_journal_add_disjunction(j)) ||
1093 (r = sd_journal_add_match(j, m3, 0)) ||
1094 (r = sd_journal_add_match(j, muid, 0)) ||
1095 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1097 /* Look for messages from authorized daemons about this service */
1098 (r = sd_journal_add_disjunction(j)) ||
1099 (r = sd_journal_add_match(j, m4, 0)) ||
1100 (r = sd_journal_add_match(j, muid, 0)) ||
1101 (r = sd_journal_add_match(j, "_UID=0", 0))
1104 if (r == 0 && endswith(unit, ".slice")) {
1105 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1107 /* Show all messages belonging to a slice */
1109 (r = sd_journal_add_disjunction(j)) ||
1110 (r = sd_journal_add_match(j, m5, 0)) ||
1111 (r = sd_journal_add_match(j, muid, 0))
1118 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1119 _cleanup_close_pipe_ int pair[2] = { -1, -1 };
1120 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1130 if (!filename_is_safe(machine))
1133 r = container_get_leader(machine, &pid);
1137 r = namespace_open(pid, &pidnsfd, &mntnsfd, &rootfd);
1141 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1151 close_nointr_nofail(pair[0]);
1154 r = namespace_enter(pidnsfd, mntnsfd, rootfd);
1156 _exit(EXIT_FAILURE);
1158 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1160 _exit(EXIT_FAILURE);
1162 k = loop_read(fd, buf, 36, false);
1163 close_nointr_nofail(fd);
1165 _exit(EXIT_FAILURE);
1167 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1169 _exit(EXIT_FAILURE);
1171 _exit(EXIT_SUCCESS);
1174 close_nointr_nofail(pair[1]);
1177 r = wait_for_terminate(child, &si);
1178 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1179 return r < 0 ? r : -EIO;
1181 k = recv(pair[0], buf, 36, 0);
1186 r = sd_id128_from_string(buf, boot_id);
1193 int add_match_this_boot(sd_journal *j, const char *machine) {
1194 char match[9+32+1] = "_BOOT_ID=";
1201 r = get_boot_id_for_machine(machine, &boot_id);
1203 log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1207 r = sd_id128_get_boot(&boot_id);
1209 log_error("Failed to get boot id: %s", strerror(-r));
1214 sd_id128_to_string(boot_id, match + 9);
1215 r = sd_journal_add_match(j, match, strlen(match));
1217 log_error("Failed to add match: %s", strerror(-r));
1221 r = sd_journal_add_conjunction(j);
1228 int show_journal_by_unit(
1240 _cleanup_journal_close_ sd_journal*j = NULL;
1242 int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1245 assert(mode < _OUTPUT_MODE_MAX);
1251 r = sd_journal_open(&j, jflags);
1255 r = add_match_this_boot(j, NULL);
1260 r = add_matches_for_unit(j, unit);
1262 r = add_matches_for_user_unit(j, unit, uid);
1266 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1267 _cleanup_free_ char *filter;
1269 filter = journal_make_match_string(j);
1270 log_debug("Journal filter: %s", filter);
1273 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1276 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1277 [OUTPUT_SHORT] = "short",
1278 [OUTPUT_SHORT_ISO] = "short-iso",
1279 [OUTPUT_SHORT_PRECISE] = "short-precise",
1280 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1281 [OUTPUT_VERBOSE] = "verbose",
1282 [OUTPUT_EXPORT] = "export",
1283 [OUTPUT_JSON] = "json",
1284 [OUTPUT_JSON_PRETTY] = "json-pretty",
1285 [OUTPUT_JSON_SSE] = "json-sse",
1286 [OUTPUT_CAT] = "cat"
1289 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);