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/>.
24 #include <sys/socket.h>
28 #include "logs-show.h"
33 #include "journal-internal.h"
34 #include "formats-util.h"
35 #include "process-util.h"
36 #include "terminal-util.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);
275 return log_error_errno(r, "Failed to get journal fields: %m");
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 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
301 fprintf(f, "[%5llu.%06llu]",
302 (unsigned long long) (t / USEC_PER_SEC),
303 (unsigned long long) (t % USEC_PER_SEC));
305 n += 1 + 5 + 1 + 6 + 1;
312 struct tm *(*gettime_r)(const time_t *, struct tm *);
315 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
318 r = safe_atou64(realtime, &x);
321 r = sd_journal_get_realtime_usec(j, &x);
324 return log_error_errno(r, "Failed to get realtime timestamp: %m");
326 t = (time_t) (x / USEC_PER_SEC);
329 case OUTPUT_SHORT_ISO:
330 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
332 case OUTPUT_SHORT_PRECISE:
333 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
335 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
336 ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
340 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
344 log_error("Failed to format time.");
352 if (hostname && shall_print(hostname, hostname_len, flags)) {
353 fprintf(f, " %.*s", (int) hostname_len, hostname);
354 n += hostname_len + 1;
357 if (identifier && shall_print(identifier, identifier_len, flags)) {
358 fprintf(f, " %.*s", (int) identifier_len, identifier);
359 n += identifier_len + 1;
360 } else if (comm && shall_print(comm, comm_len, flags)) {
361 fprintf(f, " %.*s", (int) comm_len, comm);
364 fputs(" unknown", f);
366 if (pid && shall_print(pid, pid_len, flags)) {
367 fprintf(f, "[%.*s]", (int) pid_len, pid);
369 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
370 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
371 n += fake_pid_len + 2;
374 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
375 char bytes[FORMAT_BYTES_MAX];
376 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
380 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
383 if (flags & OUTPUT_CATALOG)
389 static int output_verbose(
398 _cleanup_free_ char *cursor = NULL;
400 char ts[FORMAT_TIMESTAMP_MAX + 7];
406 sd_journal_set_data_threshold(j, 0);
408 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
410 log_debug("Source realtime timestamp not found");
412 return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m");
414 _cleanup_free_ char *value = NULL;
417 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
419 log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
421 r = safe_atou64(value, &realtime);
423 log_debug_errno(r, "Failed to parse realtime timestamp: %m");
428 r = sd_journal_get_realtime_usec(j, &realtime);
430 return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m");
433 r = sd_journal_get_cursor(j, &cursor);
435 return log_error_errno(r, "Failed to get cursor: %m");
437 fprintf(f, "%s [%s]\n",
439 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
440 format_timestamp_us(ts, sizeof(ts), realtime),
443 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
446 const char *on = "", *off = "";
448 c = memchr(data, '=', length);
450 log_error("Invalid field.");
453 fieldlen = c - (const char*) data;
455 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
456 on = ANSI_HIGHLIGHT_ON;
457 off = ANSI_HIGHLIGHT_OFF;
460 if (flags & OUTPUT_SHOW_ALL ||
461 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
462 && utf8_is_printable(data, length))) {
463 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
464 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
467 char bytes[FORMAT_BYTES_MAX];
469 fprintf(f, " %s%.*s=[%s blob data]%s\n",
471 (int) (c - (const char*) data),
473 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
481 if (flags & OUTPUT_CATALOG)
487 static int output_export(
497 usec_t realtime, monotonic;
498 _cleanup_free_ char *cursor = NULL;
504 sd_journal_set_data_threshold(j, 0);
506 r = sd_journal_get_realtime_usec(j, &realtime);
508 return log_error_errno(r, "Failed to get realtime timestamp: %m");
510 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
512 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
514 r = sd_journal_get_cursor(j, &cursor);
516 return log_error_errno(r, "Failed to get cursor: %m");
520 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
521 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
526 sd_id128_to_string(boot_id, sid));
528 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
530 /* We already printed the boot id, from the data in
531 * the header, hence let's suppress it here */
533 startswith(data, "_BOOT_ID="))
536 if (utf8_is_printable_newline(data, length, false))
537 fwrite(data, length, 1, f);
542 c = memchr(data, '=', length);
544 log_error("Invalid field.");
548 fwrite(data, c - (const char*) data, 1, f);
550 le64 = htole64(length - (c - (const char*) data) - 1);
551 fwrite(&le64, sizeof(le64), 1, f);
552 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
575 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
579 else if (!utf8_is_printable(p, l)) {
580 bool not_first = false;
586 fprintf(f, ", %u", (uint8_t) *p);
589 fprintf(f, "%u", (uint8_t) *p);
601 if (*p == '"' || *p == '\\') {
604 } else if (*p == '\n')
607 fprintf(f, "\\u%04x", *p);
619 static int output_json(
626 uint64_t realtime, monotonic;
627 _cleanup_free_ char *cursor = NULL;
634 bool done, separator;
638 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
640 r = sd_journal_get_realtime_usec(j, &realtime);
642 return log_error_errno(r, "Failed to get realtime timestamp: %m");
644 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
646 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
648 r = sd_journal_get_cursor(j, &cursor);
650 return log_error_errno(r, "Failed to get cursor: %m");
652 if (mode == OUTPUT_JSON_PRETTY)
655 "\t\"__CURSOR\" : \"%s\",\n"
656 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
657 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
658 "\t\"_BOOT_ID\" : \"%s\"",
662 sd_id128_to_string(boot_id, sid));
664 if (mode == OUTPUT_JSON_SSE)
668 "{ \"__CURSOR\" : \"%s\", "
669 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
670 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
671 "\"_BOOT_ID\" : \"%s\"",
675 sd_id128_to_string(boot_id, sid));
678 h = hashmap_new(&string_hash_ops);
682 /* First round, iterate through the entry and count how often each field appears */
683 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
689 memcmp(data, "_BOOT_ID=", 9) == 0)
692 eq = memchr(data, '=', length);
696 n = strndup(data, eq - (const char*) data);
702 u = PTR_TO_UINT(hashmap_get(h, n));
704 r = hashmap_put(h, n, UINT_TO_PTR(1));
711 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
727 SD_JOURNAL_FOREACH_DATA(j, data, length) {
733 /* We already printed the boot id, from the data in
734 * the header, hence let's suppress it here */
736 memcmp(data, "_BOOT_ID=", 9) == 0)
739 eq = memchr(data, '=', length);
744 if (mode == OUTPUT_JSON_PRETTY)
750 m = eq - (const char*) data;
752 n = strndup(data, m);
758 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
760 /* We already printed this, let's jump to the next */
766 /* Field only appears once, output it directly */
768 json_escape(f, data, m, flags);
771 json_escape(f, eq + 1, length - m - 1, flags);
773 hashmap_remove(h, n);
782 /* Field appears multiple times, output it as array */
783 json_escape(f, data, m, flags);
785 json_escape(f, eq + 1, length - m - 1, flags);
787 /* Iterate through the end of the list */
789 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
793 if (memcmp(data, n, m) != 0)
796 if (((const char*) data)[m] != '=')
800 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
805 hashmap_remove(h, n);
809 /* Iterate data fields form the beginning */
819 if (mode == OUTPUT_JSON_PRETTY)
821 else if (mode == OUTPUT_JSON_SSE)
829 while ((k = hashmap_steal_first_key(h)))
837 static int output_cat(
851 sd_journal_set_data_threshold(j, 0);
853 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
855 /* An entry without MESSAGE=? */
859 return log_error_errno(r, "Failed to get data: %m");
864 fwrite((const char*) data + 8, 1, l - 8, f);
870 static int (*output_funcs[_OUTPUT_MODE_MAX])(
875 OutputFlags flags) = {
877 [OUTPUT_SHORT] = output_short,
878 [OUTPUT_SHORT_ISO] = output_short,
879 [OUTPUT_SHORT_PRECISE] = output_short,
880 [OUTPUT_SHORT_MONOTONIC] = output_short,
881 [OUTPUT_VERBOSE] = output_verbose,
882 [OUTPUT_EXPORT] = output_export,
883 [OUTPUT_JSON] = output_json,
884 [OUTPUT_JSON_PRETTY] = output_json,
885 [OUTPUT_JSON_SSE] = output_json,
886 [OUTPUT_CAT] = output_cat
899 assert(mode < _OUTPUT_MODE_MAX);
902 n_columns = columns();
904 ret = output_funcs[mode](f, j, mode, n_columns, flags);
907 if (ellipsized && ret > 0)
913 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
917 if (!(*flags & OUTPUT_BEGIN_NEWLINE))
920 /* Print a beginning new line if that's request, but only once
921 * on the first line we print. */
924 *flags &= ~OUTPUT_BEGIN_NEWLINE;
928 static int show_journal(FILE *f,
939 bool need_seek = false;
940 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
944 assert(mode < _OUTPUT_MODE_MAX);
947 r = sd_journal_seek_tail(j);
949 return log_error_errno(r, "Failed to seek to tail: %m");
951 r = sd_journal_previous_skip(j, how_many);
953 return log_error_errno(r, "Failed to skip previous: %m");
960 r = sd_journal_next(j);
962 return log_error_errno(r, "Failed to iterate through journal: %m");
970 if (not_before > 0) {
971 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
973 /* -ESTALE is returned if the
974 timestamp is not from this boot */
978 return log_error_errno(r, "Failed to get journal time: %m");
980 if (usec < not_before)
985 maybe_print_begin_newline(f, &flags);
987 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
992 if (warn_cutoff && line < how_many && not_before > 0) {
996 /* Check whether the cutoff line is too early */
998 r = sd_id128_get_boot(&boot_id);
1000 return log_error_errno(r, "Failed to get boot id: %m");
1002 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1004 return log_error_errno(r, "Failed to get journal cutoff time: %m");
1006 if (r > 0 && not_before < cutoff) {
1007 maybe_print_begin_newline(f, &flags);
1008 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1011 warn_cutoff = false;
1014 if (!(flags & OUTPUT_FOLLOW))
1017 r = sd_journal_wait(j, USEC_INFINITY);
1019 return log_error_errno(r, "Failed to wait for journal: %m");
1026 int add_matches_for_unit(sd_journal *j, const char *unit) {
1028 char *m1, *m2, *m3, *m4;
1033 m1 = strjoina("_SYSTEMD_UNIT=", unit);
1034 m2 = strjoina("COREDUMP_UNIT=", unit);
1035 m3 = strjoina("UNIT=", unit);
1036 m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit);
1039 /* Look for messages from the service itself */
1040 (r = sd_journal_add_match(j, m1, 0)) ||
1042 /* Look for coredumps of the service */
1043 (r = sd_journal_add_disjunction(j)) ||
1044 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1045 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1046 (r = sd_journal_add_match(j, m2, 0)) ||
1048 /* Look for messages from PID 1 about this service */
1049 (r = sd_journal_add_disjunction(j)) ||
1050 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1051 (r = sd_journal_add_match(j, m3, 0)) ||
1053 /* Look for messages from authorized daemons about this service */
1054 (r = sd_journal_add_disjunction(j)) ||
1055 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1056 (r = sd_journal_add_match(j, m4, 0))
1059 if (r == 0 && endswith(unit, ".slice")) {
1060 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1062 /* Show all messages belonging to a slice */
1064 (r = sd_journal_add_disjunction(j)) ||
1065 (r = sd_journal_add_match(j, m5, 0))
1072 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1074 char *m1, *m2, *m3, *m4;
1075 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1080 m1 = strjoina("_SYSTEMD_USER_UNIT=", unit);
1081 m2 = strjoina("USER_UNIT=", unit);
1082 m3 = strjoina("COREDUMP_USER_UNIT=", unit);
1083 m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit);
1084 sprintf(muid, "_UID="UID_FMT, uid);
1087 /* Look for messages from the user service itself */
1088 (r = sd_journal_add_match(j, m1, 0)) ||
1089 (r = sd_journal_add_match(j, muid, 0)) ||
1091 /* Look for messages from systemd about this service */
1092 (r = sd_journal_add_disjunction(j)) ||
1093 (r = sd_journal_add_match(j, m2, 0)) ||
1094 (r = sd_journal_add_match(j, muid, 0)) ||
1096 /* Look for coredumps of the service */
1097 (r = sd_journal_add_disjunction(j)) ||
1098 (r = sd_journal_add_match(j, m3, 0)) ||
1099 (r = sd_journal_add_match(j, muid, 0)) ||
1100 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1102 /* Look for messages from authorized daemons about this service */
1103 (r = sd_journal_add_disjunction(j)) ||
1104 (r = sd_journal_add_match(j, m4, 0)) ||
1105 (r = sd_journal_add_match(j, muid, 0)) ||
1106 (r = sd_journal_add_match(j, "_UID=0", 0))
1109 if (r == 0 && endswith(unit, ".slice")) {
1110 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1112 /* Show all messages belonging to a slice */
1114 (r = sd_journal_add_disjunction(j)) ||
1115 (r = sd_journal_add_match(j, m5, 0)) ||
1116 (r = sd_journal_add_match(j, muid, 0))
1123 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1124 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1125 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1135 if (!machine_name_is_valid(machine))
1138 r = container_get_leader(machine, &pid);
1142 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1146 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1156 pair[0] = safe_close(pair[0]);
1158 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1160 _exit(EXIT_FAILURE);
1162 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1164 _exit(EXIT_FAILURE);
1166 r = loop_read_exact(fd, buf, 36, false);
1169 _exit(EXIT_FAILURE);
1171 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1173 _exit(EXIT_FAILURE);
1175 _exit(EXIT_SUCCESS);
1178 pair[1] = safe_close(pair[1]);
1180 r = wait_for_terminate(child, &si);
1181 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1182 return r < 0 ? r : -EIO;
1184 k = recv(pair[0], buf, 36, 0);
1189 r = sd_id128_from_string(buf, boot_id);
1196 int add_match_this_boot(sd_journal *j, const char *machine) {
1197 char match[9+32+1] = "_BOOT_ID=";
1204 r = get_boot_id_for_machine(machine, &boot_id);
1206 return log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
1208 r = sd_id128_get_boot(&boot_id);
1210 return log_error_errno(r, "Failed to get boot id: %m");
1213 sd_id128_to_string(boot_id, match + 9);
1214 r = sd_journal_add_match(j, match, strlen(match));
1216 return log_error_errno(r, "Failed to add match: %m");
1218 r = sd_journal_add_conjunction(j);
1220 return log_error_errno(r, "Failed to add conjunction: %m");
1225 int show_journal_by_unit(
1234 int journal_open_flags,
1238 _cleanup_journal_close_ sd_journal*j = NULL;
1242 assert(mode < _OUTPUT_MODE_MAX);
1248 r = sd_journal_open(&j, journal_open_flags);
1250 return log_error_errno(r, "Failed to open journal: %m");
1252 r = add_match_this_boot(j, NULL);
1257 r = add_matches_for_unit(j, unit);
1259 r = add_matches_for_user_unit(j, unit, uid);
1261 return log_error_errno(r, "Failed to add unit matches: %m");
1263 if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1264 _cleanup_free_ char *filter;
1266 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);