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;
127 /* A special case: make sure that we print a newline when
128 the message is empty. */
129 if (message_len == 0)
133 pos < message + message_len;
134 pos = end + 1, line++) {
135 bool continuation = line > 0;
138 for (end = pos; end < message + message_len && *end != '\n'; end++)
143 /* We need to figure out when we are showing not-last line, *and*
144 * will skip subsequent lines. In that case, we will put the dots
145 * at the end of the line, instead of putting dots in the middle
149 line + 1 == PRINT_LINE_THRESHOLD ||
150 end + 1 >= message + PRINT_CHAR_THRESHOLD;
152 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
153 (prefix + len + 1 < n_columns && !tail_line)) {
154 fprintf(f, "%*s%s%.*s%s\n",
155 continuation * prefix, "",
156 color_on, len, pos, color_off);
160 /* Beyond this point, ellipsization will happen. */
163 if (prefix < n_columns && n_columns - prefix >= 3) {
164 if (n_columns - prefix > (unsigned) len + 3)
165 fprintf(f, "%*s%s%.*s...%s\n",
166 continuation * prefix, "",
167 color_on, len, pos, color_off);
169 _cleanup_free_ char *e;
171 e = ellipsize_mem(pos, len, n_columns - prefix,
172 tail_line ? 100 : 90);
174 fprintf(f, "%*s%s%.*s%s\n",
175 continuation * prefix, "",
176 color_on, len, pos, color_off);
178 fprintf(f, "%*s%s%s%s\n",
179 continuation * prefix, "",
180 color_on, e, color_off);
192 static int output_short(
203 _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
204 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;
206 bool ellipsized = false;
211 /* Set the threshold to one bigger than the actual print
212 * threshold, so that if the line is actually longer than what
213 * we're willing to print, ellipsization will occur. This way
214 * we won't output a misleading line without any indication of
217 sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
219 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
221 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
227 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
233 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
239 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
245 r = parse_field(data, length, "_PID=", &pid, &pid_len);
251 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
257 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
263 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
269 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
280 if (!(flags & OUTPUT_SHOW_ALL))
281 strip_tab_ansi(&message, &message_len);
283 if (priority_len == 1 && *priority >= '0' && *priority <= '7')
286 if (mode == OUTPUT_SHORT_MONOTONIC) {
293 r = safe_atou64(monotonic, &t);
296 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
299 log_error_errno(r, "Failed to get monotonic timestamp: %m");
303 fprintf(f, "[%5llu.%06llu]",
304 (unsigned long long) (t / USEC_PER_SEC),
305 (unsigned long long) (t % USEC_PER_SEC));
307 n += 1 + 5 + 1 + 6 + 1;
314 struct tm *(*gettime_r)(const time_t *, struct tm *);
317 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
320 r = safe_atou64(realtime, &x);
323 r = sd_journal_get_realtime_usec(j, &x);
326 log_error_errno(r, "Failed to get realtime timestamp: %m");
330 t = (time_t) (x / USEC_PER_SEC);
333 case OUTPUT_SHORT_ISO:
334 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
336 case OUTPUT_SHORT_PRECISE:
337 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
339 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
340 ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
344 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
348 log_error("Failed to format time.");
356 if (hostname && shall_print(hostname, hostname_len, flags)) {
357 fprintf(f, " %.*s", (int) hostname_len, hostname);
358 n += hostname_len + 1;
361 if (identifier && shall_print(identifier, identifier_len, flags)) {
362 fprintf(f, " %.*s", (int) identifier_len, identifier);
363 n += identifier_len + 1;
364 } else if (comm && shall_print(comm, comm_len, flags)) {
365 fprintf(f, " %.*s", (int) comm_len, comm);
368 fputs(" unknown", f);
370 if (pid && shall_print(pid, pid_len, flags)) {
371 fprintf(f, "[%.*s]", (int) pid_len, pid);
373 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
374 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
375 n += fake_pid_len + 2;
378 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
379 char bytes[FORMAT_BYTES_MAX];
380 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
384 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
387 if (flags & OUTPUT_CATALOG)
393 static int output_verbose(
402 _cleanup_free_ char *cursor = NULL;
404 char ts[FORMAT_TIMESTAMP_MAX + 7];
410 sd_journal_set_data_threshold(j, 0);
412 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
414 log_debug("Source realtime timestamp not found");
416 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
417 "Failed to get source realtime timestamp: %s", strerror(-r));
420 _cleanup_free_ char *value = NULL;
423 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
425 log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
427 r = safe_atou64(value, &realtime);
429 log_debug_errno(r, "Failed to parse realtime timestamp: %m");
434 r = sd_journal_get_realtime_usec(j, &realtime);
436 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
437 "Failed to get realtime timestamp: %s", strerror(-r));
442 r = sd_journal_get_cursor(j, &cursor);
444 log_error_errno(r, "Failed to get cursor: %m");
448 fprintf(f, "%s [%s]\n",
450 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
451 format_timestamp_us(ts, sizeof(ts), realtime),
454 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
457 const char *on = "", *off = "";
459 c = memchr(data, '=', length);
461 log_error("Invalid field.");
464 fieldlen = c - (const char*) data;
466 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
467 on = ANSI_HIGHLIGHT_ON;
468 off = ANSI_HIGHLIGHT_OFF;
471 if (flags & OUTPUT_SHOW_ALL ||
472 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
473 && utf8_is_printable(data, length))) {
474 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
475 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
478 char bytes[FORMAT_BYTES_MAX];
480 fprintf(f, " %s%.*s=[%s blob data]%s\n",
482 (int) (c - (const char*) data),
484 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
492 if (flags & OUTPUT_CATALOG)
498 static int output_export(
508 usec_t realtime, monotonic;
509 _cleanup_free_ char *cursor = NULL;
515 sd_journal_set_data_threshold(j, 0);
517 r = sd_journal_get_realtime_usec(j, &realtime);
519 log_error_errno(r, "Failed to get realtime timestamp: %m");
523 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
525 log_error_errno(r, "Failed to get monotonic timestamp: %m");
529 r = sd_journal_get_cursor(j, &cursor);
531 log_error_errno(r, "Failed to get cursor: %m");
537 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
538 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
543 sd_id128_to_string(boot_id, sid));
545 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
547 /* We already printed the boot id, from the data in
548 * the header, hence let's suppress it here */
550 startswith(data, "_BOOT_ID="))
553 if (utf8_is_printable_newline(data, length, false))
554 fwrite(data, length, 1, f);
559 c = memchr(data, '=', length);
561 log_error("Invalid field.");
565 fwrite(data, c - (const char*) data, 1, f);
567 le64 = htole64(length - (c - (const char*) data) - 1);
568 fwrite(&le64, sizeof(le64), 1, f);
569 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
592 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
596 else if (!utf8_is_printable(p, l)) {
597 bool not_first = false;
603 fprintf(f, ", %u", (uint8_t) *p);
606 fprintf(f, "%u", (uint8_t) *p);
618 if (*p == '"' || *p == '\\') {
621 } else if (*p == '\n')
624 fprintf(f, "\\u%04x", *p);
636 static int output_json(
643 uint64_t realtime, monotonic;
644 _cleanup_free_ char *cursor = NULL;
651 bool done, separator;
655 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
657 r = sd_journal_get_realtime_usec(j, &realtime);
659 log_error_errno(r, "Failed to get realtime timestamp: %m");
663 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
665 log_error_errno(r, "Failed to get monotonic timestamp: %m");
669 r = sd_journal_get_cursor(j, &cursor);
671 log_error_errno(r, "Failed to get cursor: %m");
675 if (mode == OUTPUT_JSON_PRETTY)
678 "\t\"__CURSOR\" : \"%s\",\n"
679 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
680 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
681 "\t\"_BOOT_ID\" : \"%s\"",
685 sd_id128_to_string(boot_id, sid));
687 if (mode == OUTPUT_JSON_SSE)
691 "{ \"__CURSOR\" : \"%s\", "
692 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
693 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
694 "\"_BOOT_ID\" : \"%s\"",
698 sd_id128_to_string(boot_id, sid));
701 h = hashmap_new(&string_hash_ops);
705 /* First round, iterate through the entry and count how often each field appears */
706 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
712 memcmp(data, "_BOOT_ID=", 9) == 0)
715 eq = memchr(data, '=', length);
719 n = strndup(data, eq - (const char*) data);
725 u = PTR_TO_UINT(hashmap_get(h, n));
727 r = hashmap_put(h, n, UINT_TO_PTR(1));
733 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
747 SD_JOURNAL_FOREACH_DATA(j, data, length) {
753 /* We already printed the boot id, from the data in
754 * the header, hence let's suppress it here */
756 memcmp(data, "_BOOT_ID=", 9) == 0)
759 eq = memchr(data, '=', length);
764 if (mode == OUTPUT_JSON_PRETTY)
770 m = eq - (const char*) data;
772 n = strndup(data, m);
778 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
780 /* We already printed this, let's jump to the next */
786 /* Field only appears once, output it directly */
788 json_escape(f, data, m, flags);
791 json_escape(f, eq + 1, length - m - 1, flags);
793 hashmap_remove(h, n);
802 /* Field appears multiple times, output it as array */
803 json_escape(f, data, m, flags);
805 json_escape(f, eq + 1, length - m - 1, flags);
807 /* Iterate through the end of the list */
809 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
813 if (memcmp(data, n, m) != 0)
816 if (((const char*) data)[m] != '=')
820 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
825 hashmap_remove(h, n);
829 /* Iterate data fields form the beginning */
839 if (mode == OUTPUT_JSON_PRETTY)
841 else if (mode == OUTPUT_JSON_SSE)
849 while ((k = hashmap_steal_first_key(h)))
857 static int output_cat(
871 sd_journal_set_data_threshold(j, 0);
873 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
875 /* An entry without MESSAGE=? */
879 log_error_errno(r, "Failed to get data: %m");
885 fwrite((const char*) data + 8, 1, l - 8, f);
891 static int (*output_funcs[_OUTPUT_MODE_MAX])(
896 OutputFlags flags) = {
898 [OUTPUT_SHORT] = output_short,
899 [OUTPUT_SHORT_ISO] = output_short,
900 [OUTPUT_SHORT_PRECISE] = output_short,
901 [OUTPUT_SHORT_MONOTONIC] = output_short,
902 [OUTPUT_VERBOSE] = output_verbose,
903 [OUTPUT_EXPORT] = output_export,
904 [OUTPUT_JSON] = output_json,
905 [OUTPUT_JSON_PRETTY] = output_json,
906 [OUTPUT_JSON_SSE] = output_json,
907 [OUTPUT_CAT] = output_cat
920 assert(mode < _OUTPUT_MODE_MAX);
923 n_columns = columns();
925 ret = output_funcs[mode](f, j, mode, n_columns, flags);
928 if (ellipsized && ret > 0)
934 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
938 if (!(*flags & OUTPUT_BEGIN_NEWLINE))
941 /* Print a beginning new line if that's request, but only once
942 * on the first line we print. */
945 *flags &= ~OUTPUT_BEGIN_NEWLINE;
949 static int show_journal(FILE *f,
960 bool need_seek = false;
961 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
965 assert(mode < _OUTPUT_MODE_MAX);
968 r = sd_journal_seek_tail(j);
972 r = sd_journal_previous_skip(j, how_many);
981 r = sd_journal_next(j);
991 if (not_before > 0) {
992 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
994 /* -ESTALE is returned if the
995 timestamp is not from this boot */
1001 if (usec < not_before)
1006 maybe_print_begin_newline(f, &flags);
1008 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
1013 if (warn_cutoff && line < how_many && not_before > 0) {
1017 /* Check whether the cutoff line is too early */
1019 r = sd_id128_get_boot(&boot_id);
1023 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1027 if (r > 0 && not_before < cutoff) {
1028 maybe_print_begin_newline(f, &flags);
1029 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1032 warn_cutoff = false;
1035 if (!(flags & OUTPUT_FOLLOW))
1038 r = sd_journal_wait(j, USEC_INFINITY);
1048 int add_matches_for_unit(sd_journal *j, const char *unit) {
1050 char *m1, *m2, *m3, *m4;
1055 m1 = strappenda("_SYSTEMD_UNIT=", unit);
1056 m2 = strappenda("COREDUMP_UNIT=", unit);
1057 m3 = strappenda("UNIT=", unit);
1058 m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1061 /* Look for messages from the service itself */
1062 (r = sd_journal_add_match(j, m1, 0)) ||
1064 /* Look for coredumps of the service */
1065 (r = sd_journal_add_disjunction(j)) ||
1066 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1067 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1068 (r = sd_journal_add_match(j, m2, 0)) ||
1070 /* Look for messages from PID 1 about this service */
1071 (r = sd_journal_add_disjunction(j)) ||
1072 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1073 (r = sd_journal_add_match(j, m3, 0)) ||
1075 /* Look for messages from authorized daemons about this service */
1076 (r = sd_journal_add_disjunction(j)) ||
1077 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1078 (r = sd_journal_add_match(j, m4, 0))
1081 if (r == 0 && endswith(unit, ".slice")) {
1082 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1084 /* Show all messages belonging to a slice */
1086 (r = sd_journal_add_disjunction(j)) ||
1087 (r = sd_journal_add_match(j, m5, 0))
1094 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1096 char *m1, *m2, *m3, *m4;
1097 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1102 m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1103 m2 = strappenda("USER_UNIT=", unit);
1104 m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1105 m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1106 sprintf(muid, "_UID="UID_FMT, uid);
1109 /* Look for messages from the user service itself */
1110 (r = sd_journal_add_match(j, m1, 0)) ||
1111 (r = sd_journal_add_match(j, muid, 0)) ||
1113 /* Look for messages from systemd about this service */
1114 (r = sd_journal_add_disjunction(j)) ||
1115 (r = sd_journal_add_match(j, m2, 0)) ||
1116 (r = sd_journal_add_match(j, muid, 0)) ||
1118 /* Look for coredumps of the service */
1119 (r = sd_journal_add_disjunction(j)) ||
1120 (r = sd_journal_add_match(j, m3, 0)) ||
1121 (r = sd_journal_add_match(j, muid, 0)) ||
1122 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1124 /* Look for messages from authorized daemons about this service */
1125 (r = sd_journal_add_disjunction(j)) ||
1126 (r = sd_journal_add_match(j, m4, 0)) ||
1127 (r = sd_journal_add_match(j, muid, 0)) ||
1128 (r = sd_journal_add_match(j, "_UID=0", 0))
1131 if (r == 0 && endswith(unit, ".slice")) {
1132 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1134 /* Show all messages belonging to a slice */
1136 (r = sd_journal_add_disjunction(j)) ||
1137 (r = sd_journal_add_match(j, m5, 0)) ||
1138 (r = sd_journal_add_match(j, muid, 0))
1145 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1146 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1147 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1157 if (!machine_name_is_valid(machine))
1160 r = container_get_leader(machine, &pid);
1164 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1168 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1178 pair[0] = safe_close(pair[0]);
1180 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1182 _exit(EXIT_FAILURE);
1184 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1186 _exit(EXIT_FAILURE);
1188 k = loop_read(fd, buf, 36, false);
1191 _exit(EXIT_FAILURE);
1193 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1195 _exit(EXIT_FAILURE);
1197 _exit(EXIT_SUCCESS);
1200 pair[1] = safe_close(pair[1]);
1202 r = wait_for_terminate(child, &si);
1203 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1204 return r < 0 ? r : -EIO;
1206 k = recv(pair[0], buf, 36, 0);
1211 r = sd_id128_from_string(buf, boot_id);
1218 int add_match_this_boot(sd_journal *j, const char *machine) {
1219 char match[9+32+1] = "_BOOT_ID=";
1226 r = get_boot_id_for_machine(machine, &boot_id);
1228 log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
1232 r = sd_id128_get_boot(&boot_id);
1234 log_error_errno(r, "Failed to get boot id: %m");
1239 sd_id128_to_string(boot_id, match + 9);
1240 r = sd_journal_add_match(j, match, strlen(match));
1242 log_error_errno(r, "Failed to add match: %m");
1246 r = sd_journal_add_conjunction(j);
1253 int show_journal_by_unit(
1265 _cleanup_journal_close_ sd_journal*j = NULL;
1267 int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1270 assert(mode < _OUTPUT_MODE_MAX);
1276 r = sd_journal_open(&j, jflags);
1280 r = add_match_this_boot(j, NULL);
1285 r = add_matches_for_unit(j, unit);
1287 r = add_matches_for_user_unit(j, unit, uid);
1291 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1292 _cleanup_free_ char *filter;
1294 filter = journal_make_match_string(j);
1295 log_debug("Journal filter: %s", filter);
1298 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1301 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1302 [OUTPUT_SHORT] = "short",
1303 [OUTPUT_SHORT_ISO] = "short-iso",
1304 [OUTPUT_SHORT_PRECISE] = "short-precise",
1305 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1306 [OUTPUT_VERBOSE] = "verbose",
1307 [OUTPUT_EXPORT] = "export",
1308 [OUTPUT_JSON] = "json",
1309 [OUTPUT_JSON_PRETTY] = "json-pretty",
1310 [OUTPUT_JSON_SSE] = "json-sse",
1311 [OUTPUT_CAT] = "cat"
1314 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);