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/>.
25 #include <sys/socket.h>
28 #include "alloc-util.h"
30 #include "formats-util.h"
32 #include "hostname-util.h"
34 #include "journal-internal.h"
36 #include "logs-show.h"
37 #include "parse-util.h"
38 #include "process-util.h"
39 #include "string-table.h"
40 #include "string-util.h"
41 #include "terminal-util.h"
45 /* up to three lines (each up to 100 characters) or 300 characters, whichever is less */
46 #define PRINT_LINE_THRESHOLD 3
47 #define PRINT_CHAR_THRESHOLD 300
49 #define JSON_THRESHOLD 4096
51 static int print_catalog(FILE *f
, sd_journal
*j
) {
53 _cleanup_free_
char *t
= NULL
, *z
= NULL
;
56 r
= sd_journal_get_catalog(j
, &t
);
60 z
= strreplace(strstrip(t
), "\n", "\n-- ");
71 static int parse_field(const void *data
, size_t length
, const char *field
, char **target
, size_t *target_size
) {
84 if (memcmp(data
, field
, fl
))
92 memcpy(buf
, (const char*) data
+ fl
, nl
);
102 static bool shall_print(const char *p
, size_t l
, OutputFlags flags
) {
105 if (flags
& OUTPUT_SHOW_ALL
)
108 if (l
>= PRINT_CHAR_THRESHOLD
)
111 if (!utf8_is_printable(p
, l
))
117 static bool print_multiline(FILE *f
, unsigned prefix
, unsigned n_columns
, OutputFlags flags
, int priority
, const char* message
, size_t message_len
) {
118 const char *color_on
= "", *color_off
= "";
119 const char *pos
, *end
;
120 bool ellipsized
= false;
123 if (flags
& OUTPUT_COLOR
) {
124 if (priority
<= LOG_ERR
) {
125 color_on
= ANSI_HIGHLIGHT_RED
;
126 color_off
= ANSI_NORMAL
;
127 } else if (priority
<= LOG_NOTICE
) {
128 color_on
= ANSI_HIGHLIGHT
;
129 color_off
= ANSI_NORMAL
;
133 /* A special case: make sure that we print a newline when
134 the message is empty. */
135 if (message_len
== 0)
139 pos
< message
+ message_len
;
140 pos
= end
+ 1, line
++) {
141 bool continuation
= line
> 0;
144 for (end
= pos
; end
< message
+ message_len
&& *end
!= '\n'; end
++)
149 /* We need to figure out when we are showing not-last line, *and*
150 * will skip subsequent lines. In that case, we will put the dots
151 * at the end of the line, instead of putting dots in the middle
155 line
+ 1 == PRINT_LINE_THRESHOLD
||
156 end
+ 1 >= message
+ PRINT_CHAR_THRESHOLD
;
158 if (flags
& (OUTPUT_FULL_WIDTH
| OUTPUT_SHOW_ALL
) ||
159 (prefix
+ len
+ 1 < n_columns
&& !tail_line
)) {
160 fprintf(f
, "%*s%s%.*s%s\n",
161 continuation
* prefix
, "",
162 color_on
, len
, pos
, color_off
);
166 /* Beyond this point, ellipsization will happen. */
169 if (prefix
< n_columns
&& n_columns
- prefix
>= 3) {
170 if (n_columns
- prefix
> (unsigned) len
+ 3)
171 fprintf(f
, "%*s%s%.*s...%s\n",
172 continuation
* prefix
, "",
173 color_on
, len
, pos
, color_off
);
175 _cleanup_free_
char *e
;
177 e
= ellipsize_mem(pos
, len
, n_columns
- prefix
,
178 tail_line
? 100 : 90);
180 fprintf(f
, "%*s%s%.*s%s\n",
181 continuation
* prefix
, "",
182 color_on
, len
, pos
, color_off
);
184 fprintf(f
, "%*s%s%s%s\n",
185 continuation
* prefix
, "",
186 color_on
, e
, color_off
);
198 static int output_short(
209 _cleanup_free_
char *hostname
= NULL
, *identifier
= NULL
, *comm
= NULL
, *pid
= NULL
, *fake_pid
= NULL
, *message
= NULL
, *realtime
= NULL
, *monotonic
= NULL
, *priority
= NULL
;
210 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;
212 bool ellipsized
= false;
217 /* Set the threshold to one bigger than the actual print
218 * threshold, so that if the line is actually longer than what
219 * we're willing to print, ellipsization will occur. This way
220 * we won't output a misleading line without any indication of
223 sd_journal_set_data_threshold(j
, flags
& (OUTPUT_SHOW_ALL
|OUTPUT_FULL_WIDTH
) ? 0 : PRINT_CHAR_THRESHOLD
+ 1);
225 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
227 r
= parse_field(data
, length
, "PRIORITY=", &priority
, &priority_len
);
233 r
= parse_field(data
, length
, "_HOSTNAME=", &hostname
, &hostname_len
);
239 r
= parse_field(data
, length
, "SYSLOG_IDENTIFIER=", &identifier
, &identifier_len
);
245 r
= parse_field(data
, length
, "_COMM=", &comm
, &comm_len
);
251 r
= parse_field(data
, length
, "_PID=", &pid
, &pid_len
);
257 r
= parse_field(data
, length
, "SYSLOG_PID=", &fake_pid
, &fake_pid_len
);
263 r
= parse_field(data
, length
, "_SOURCE_REALTIME_TIMESTAMP=", &realtime
, &realtime_len
);
269 r
= parse_field(data
, length
, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic
, &monotonic_len
);
275 r
= parse_field(data
, length
, "MESSAGE=", &message
, &message_len
);
281 return log_error_errno(r
, "Failed to get journal fields: %m");
284 log_debug("Skipping message without MESSAGE= field.");
288 if (!(flags
& OUTPUT_SHOW_ALL
))
289 strip_tab_ansi(&message
, &message_len
);
291 if (priority_len
== 1 && *priority
>= '0' && *priority
<= '7')
294 if (mode
== OUTPUT_SHORT_MONOTONIC
) {
301 r
= safe_atou64(monotonic
, &t
);
304 r
= sd_journal_get_monotonic_usec(j
, &t
, &boot_id
);
307 return log_error_errno(r
, "Failed to get monotonic timestamp: %m");
309 fprintf(f
, "[%5llu.%06llu]",
310 (unsigned long long) (t
/ USEC_PER_SEC
),
311 (unsigned long long) (t
% USEC_PER_SEC
));
313 n
+= 1 + 5 + 1 + 6 + 1;
320 struct tm
*(*gettime_r
)(const time_t *, struct tm
*);
323 gettime_r
= (flags
& OUTPUT_UTC
) ? gmtime_r
: localtime_r
;
326 r
= safe_atou64(realtime
, &x
);
329 r
= sd_journal_get_realtime_usec(j
, &x
);
332 return log_error_errno(r
, "Failed to get realtime timestamp: %m");
334 t
= (time_t) (x
/ USEC_PER_SEC
);
337 case OUTPUT_SHORT_ISO
:
338 r
= strftime(buf
, sizeof(buf
), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t
, &tm
));
340 case OUTPUT_SHORT_PRECISE
:
341 r
= strftime(buf
, sizeof(buf
), "%b %d %H:%M:%S", gettime_r(&t
, &tm
));
343 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
),
344 ".%06llu", (unsigned long long) (x
% USEC_PER_SEC
));
347 r
= strftime(buf
, sizeof(buf
), "%b %d %H:%M:%S", gettime_r(&t
, &tm
));
351 log_error("Failed to format time.");
359 if (hostname
&& shall_print(hostname
, hostname_len
, flags
)) {
360 fprintf(f
, " %.*s", (int) hostname_len
, hostname
);
361 n
+= hostname_len
+ 1;
364 if (identifier
&& shall_print(identifier
, identifier_len
, flags
)) {
365 fprintf(f
, " %.*s", (int) identifier_len
, identifier
);
366 n
+= identifier_len
+ 1;
367 } else if (comm
&& shall_print(comm
, comm_len
, flags
)) {
368 fprintf(f
, " %.*s", (int) comm_len
, comm
);
371 fputs(" unknown", f
);
373 if (pid
&& shall_print(pid
, pid_len
, flags
)) {
374 fprintf(f
, "[%.*s]", (int) pid_len
, pid
);
376 } else if (fake_pid
&& shall_print(fake_pid
, fake_pid_len
, flags
)) {
377 fprintf(f
, "[%.*s]", (int) fake_pid_len
, fake_pid
);
378 n
+= fake_pid_len
+ 2;
381 if (!(flags
& OUTPUT_SHOW_ALL
) && !utf8_is_printable(message
, message_len
)) {
382 char bytes
[FORMAT_BYTES_MAX
];
383 fprintf(f
, ": [%s blob data]\n", format_bytes(bytes
, sizeof(bytes
), message_len
));
387 print_multiline(f
, n
+ 2, n_columns
, flags
, p
, message
, message_len
);
390 if (flags
& OUTPUT_CATALOG
)
396 static int output_verbose(
405 _cleanup_free_
char *cursor
= NULL
;
407 char ts
[FORMAT_TIMESTAMP_MAX
+ 7];
413 sd_journal_set_data_threshold(j
, 0);
415 r
= sd_journal_get_data(j
, "_SOURCE_REALTIME_TIMESTAMP", &data
, &length
);
417 log_debug("Source realtime timestamp not found");
419 return log_full_errno(r
== -EADDRNOTAVAIL
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get source realtime timestamp: %m");
421 _cleanup_free_
char *value
= NULL
;
424 r
= parse_field(data
, length
, "_SOURCE_REALTIME_TIMESTAMP=", &value
, &size
);
426 log_debug_errno(r
, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
428 r
= safe_atou64(value
, &realtime
);
430 log_debug_errno(r
, "Failed to parse realtime timestamp: %m");
435 r
= sd_journal_get_realtime_usec(j
, &realtime
);
437 return log_full_errno(r
== -EADDRNOTAVAIL
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get realtime timestamp: %m");
440 r
= sd_journal_get_cursor(j
, &cursor
);
442 return log_error_errno(r
, "Failed to get cursor: %m");
444 fprintf(f
, "%s [%s]\n",
446 format_timestamp_us_utc(ts
, sizeof(ts
), realtime
) :
447 format_timestamp_us(ts
, sizeof(ts
), realtime
),
450 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
453 const char *on
= "", *off
= "";
455 c
= memchr(data
, '=', length
);
457 log_error("Invalid field.");
460 fieldlen
= c
- (const char*) data
;
462 if (flags
& OUTPUT_COLOR
&& startswith(data
, "MESSAGE=")) {
467 if (flags
& OUTPUT_SHOW_ALL
||
468 (((length
< PRINT_CHAR_THRESHOLD
) || flags
& OUTPUT_FULL_WIDTH
)
469 && utf8_is_printable(data
, length
))) {
470 fprintf(f
, " %s%.*s=", on
, fieldlen
, (const char*)data
);
471 print_multiline(f
, 4 + fieldlen
+ 1, 0, OUTPUT_FULL_WIDTH
, 0, c
+ 1, length
- fieldlen
- 1);
474 char bytes
[FORMAT_BYTES_MAX
];
476 fprintf(f
, " %s%.*s=[%s blob data]%s\n",
478 (int) (c
- (const char*) data
),
480 format_bytes(bytes
, sizeof(bytes
), length
- (c
- (const char *) data
) - 1),
488 if (flags
& OUTPUT_CATALOG
)
494 static int output_export(
504 usec_t realtime
, monotonic
;
505 _cleanup_free_
char *cursor
= NULL
;
511 sd_journal_set_data_threshold(j
, 0);
513 r
= sd_journal_get_realtime_usec(j
, &realtime
);
515 return log_error_errno(r
, "Failed to get realtime timestamp: %m");
517 r
= sd_journal_get_monotonic_usec(j
, &monotonic
, &boot_id
);
519 return log_error_errno(r
, "Failed to get monotonic timestamp: %m");
521 r
= sd_journal_get_cursor(j
, &cursor
);
523 return log_error_errno(r
, "Failed to get cursor: %m");
527 "__REALTIME_TIMESTAMP="USEC_FMT
"\n"
528 "__MONOTONIC_TIMESTAMP="USEC_FMT
"\n"
533 sd_id128_to_string(boot_id
, sid
));
535 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
537 /* We already printed the boot id, from the data in
538 * the header, hence let's suppress it here */
540 startswith(data
, "_BOOT_ID="))
543 if (utf8_is_printable_newline(data
, length
, false))
544 fwrite(data
, length
, 1, f
);
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
);
582 if (!(flags
& OUTPUT_SHOW_ALL
) && l
>= JSON_THRESHOLD
)
585 else if (!utf8_is_printable(p
, l
)) {
586 bool not_first
= false;
592 fprintf(f
, ", %u", (uint8_t) *p
);
595 fprintf(f
, "%u", (uint8_t) *p
);
607 if (*p
== '"' || *p
== '\\') {
610 } else if (*p
== '\n')
612 else if ((uint8_t) *p
< ' ')
613 fprintf(f
, "\\u%04x", (uint8_t) *p
);
625 static int output_json(
632 uint64_t realtime
, monotonic
;
633 _cleanup_free_
char *cursor
= NULL
;
640 bool done
, separator
;
644 sd_journal_set_data_threshold(j
, flags
& OUTPUT_SHOW_ALL
? 0 : JSON_THRESHOLD
);
646 r
= sd_journal_get_realtime_usec(j
, &realtime
);
648 return log_error_errno(r
, "Failed to get realtime timestamp: %m");
650 r
= sd_journal_get_monotonic_usec(j
, &monotonic
, &boot_id
);
652 return log_error_errno(r
, "Failed to get monotonic timestamp: %m");
654 r
= sd_journal_get_cursor(j
, &cursor
);
656 return log_error_errno(r
, "Failed to get cursor: %m");
658 if (mode
== OUTPUT_JSON_PRETTY
)
661 "\t\"__CURSOR\" : \"%s\",\n"
662 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT
"\",\n"
663 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT
"\",\n"
664 "\t\"_BOOT_ID\" : \"%s\"",
668 sd_id128_to_string(boot_id
, sid
));
670 if (mode
== OUTPUT_JSON_SSE
)
674 "{ \"__CURSOR\" : \"%s\", "
675 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT
"\", "
676 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT
"\", "
677 "\"_BOOT_ID\" : \"%s\"",
681 sd_id128_to_string(boot_id
, sid
));
684 h
= hashmap_new(&string_hash_ops
);
688 /* First round, iterate through the entry and count how often each field appears */
689 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
695 memcmp(data
, "_BOOT_ID=", 9) == 0)
698 eq
= memchr(data
, '=', length
);
702 n
= strndup(data
, eq
- (const char*) data
);
708 u
= PTR_TO_UINT(hashmap_get(h
, n
));
710 r
= hashmap_put(h
, n
, UINT_TO_PTR(1));
717 r
= hashmap_update(h
, n
, UINT_TO_PTR(u
+ 1));
733 SD_JOURNAL_FOREACH_DATA(j
, data
, length
) {
739 /* We already printed the boot id, from the data in
740 * the header, hence let's suppress it here */
742 memcmp(data
, "_BOOT_ID=", 9) == 0)
745 eq
= memchr(data
, '=', length
);
750 if (mode
== OUTPUT_JSON_PRETTY
)
756 m
= eq
- (const char*) data
;
758 n
= strndup(data
, m
);
764 u
= PTR_TO_UINT(hashmap_get2(h
, n
, (void**) &kk
));
766 /* We already printed this, let's jump to the next */
772 /* Field only appears once, output it directly */
774 json_escape(f
, data
, m
, flags
);
777 json_escape(f
, eq
+ 1, length
- m
- 1, flags
);
779 hashmap_remove(h
, n
);
788 /* Field appears multiple times, output it as array */
789 json_escape(f
, data
, m
, flags
);
791 json_escape(f
, eq
+ 1, length
- m
- 1, flags
);
793 /* Iterate through the end of the list */
795 while (sd_journal_enumerate_data(j
, &data
, &length
) > 0) {
799 if (memcmp(data
, n
, m
) != 0)
802 if (((const char*) data
)[m
] != '=')
806 json_escape(f
, (const char*) data
+ m
+ 1, length
- m
- 1, flags
);
811 hashmap_remove(h
, n
);
815 /* Iterate data fields form the beginning */
825 if (mode
== OUTPUT_JSON_PRETTY
)
827 else if (mode
== OUTPUT_JSON_SSE
)
835 while ((k
= hashmap_steal_first_key(h
)))
843 static int output_cat(
857 sd_journal_set_data_threshold(j
, 0);
859 r
= sd_journal_get_data(j
, "MESSAGE", &data
, &l
);
861 /* An entry without MESSAGE=? */
865 return log_error_errno(r
, "Failed to get data: %m");
870 fwrite((const char*) data
+ 8, 1, l
- 8, f
);
876 static int (*output_funcs
[_OUTPUT_MODE_MAX
])(
881 OutputFlags flags
) = {
883 [OUTPUT_SHORT
] = output_short
,
884 [OUTPUT_SHORT_ISO
] = output_short
,
885 [OUTPUT_SHORT_PRECISE
] = output_short
,
886 [OUTPUT_SHORT_MONOTONIC
] = output_short
,
887 [OUTPUT_VERBOSE
] = output_verbose
,
888 [OUTPUT_EXPORT
] = output_export
,
889 [OUTPUT_JSON
] = output_json
,
890 [OUTPUT_JSON_PRETTY
] = output_json
,
891 [OUTPUT_JSON_SSE
] = output_json
,
892 [OUTPUT_CAT
] = output_cat
905 assert(mode
< _OUTPUT_MODE_MAX
);
908 n_columns
= columns();
910 ret
= output_funcs
[mode
](f
, j
, mode
, n_columns
, flags
);
913 if (ellipsized
&& ret
> 0)
919 static int maybe_print_begin_newline(FILE *f
, OutputFlags
*flags
) {
923 if (!(*flags
& OUTPUT_BEGIN_NEWLINE
))
926 /* Print a beginning new line if that's request, but only once
927 * on the first line we print. */
930 *flags
&= ~OUTPUT_BEGIN_NEWLINE
;
934 static int show_journal(FILE *f
,
945 bool need_seek
= false;
946 int warn_cutoff
= flags
& OUTPUT_WARN_CUTOFF
;
950 assert(mode
< _OUTPUT_MODE_MAX
);
953 r
= sd_journal_seek_tail(j
);
955 return log_error_errno(r
, "Failed to seek to tail: %m");
957 r
= sd_journal_previous_skip(j
, how_many
);
959 return log_error_errno(r
, "Failed to skip previous: %m");
966 r
= sd_journal_next(j
);
968 return log_error_errno(r
, "Failed to iterate through journal: %m");
976 if (not_before
> 0) {
977 r
= sd_journal_get_monotonic_usec(j
, &usec
, NULL
);
979 /* -ESTALE is returned if the
980 timestamp is not from this boot */
984 return log_error_errno(r
, "Failed to get journal time: %m");
986 if (usec
< not_before
)
991 maybe_print_begin_newline(f
, &flags
);
993 r
= output_journal(f
, j
, mode
, n_columns
, flags
, ellipsized
);
998 if (warn_cutoff
&& line
< how_many
&& not_before
> 0) {
1002 /* Check whether the cutoff line is too early */
1004 r
= sd_id128_get_boot(&boot_id
);
1006 return log_error_errno(r
, "Failed to get boot id: %m");
1008 r
= sd_journal_get_cutoff_monotonic_usec(j
, boot_id
, &cutoff
, NULL
);
1010 return log_error_errno(r
, "Failed to get journal cutoff time: %m");
1012 if (r
> 0 && not_before
< cutoff
) {
1013 maybe_print_begin_newline(f
, &flags
);
1014 fprintf(f
, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1017 warn_cutoff
= false;
1020 if (!(flags
& OUTPUT_FOLLOW
))
1023 r
= sd_journal_wait(j
, USEC_INFINITY
);
1025 return log_error_errno(r
, "Failed to wait for journal: %m");
1032 int add_matches_for_unit(sd_journal
*j
, const char *unit
) {
1034 char *m1
, *m2
, *m3
, *m4
;
1039 m1
= strjoina("_SYSTEMD_UNIT=", unit
);
1040 m2
= strjoina("COREDUMP_UNIT=", unit
);
1041 m3
= strjoina("UNIT=", unit
);
1042 m4
= strjoina("OBJECT_SYSTEMD_UNIT=", unit
);
1045 /* Look for messages from the service itself */
1046 (r
= sd_journal_add_match(j
, m1
, 0)) ||
1048 /* Look for coredumps of the service */
1049 (r
= sd_journal_add_disjunction(j
)) ||
1050 (r
= sd_journal_add_match(j
, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1051 (r
= sd_journal_add_match(j
, "_UID=0", 0)) ||
1052 (r
= sd_journal_add_match(j
, m2
, 0)) ||
1054 /* Look for messages from PID 1 about this service */
1055 (r
= sd_journal_add_disjunction(j
)) ||
1056 (r
= sd_journal_add_match(j
, "_PID=1", 0)) ||
1057 (r
= sd_journal_add_match(j
, m3
, 0)) ||
1059 /* Look for messages from authorized daemons about this service */
1060 (r
= sd_journal_add_disjunction(j
)) ||
1061 (r
= sd_journal_add_match(j
, "_UID=0", 0)) ||
1062 (r
= sd_journal_add_match(j
, m4
, 0))
1065 if (r
== 0 && endswith(unit
, ".slice")) {
1066 char *m5
= strappend("_SYSTEMD_SLICE=", unit
);
1068 /* Show all messages belonging to a slice */
1070 (r
= sd_journal_add_disjunction(j
)) ||
1071 (r
= sd_journal_add_match(j
, m5
, 0))
1078 int add_matches_for_user_unit(sd_journal
*j
, const char *unit
, uid_t uid
) {
1080 char *m1
, *m2
, *m3
, *m4
;
1081 char muid
[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t
)];
1086 m1
= strjoina("_SYSTEMD_USER_UNIT=", unit
);
1087 m2
= strjoina("USER_UNIT=", unit
);
1088 m3
= strjoina("COREDUMP_USER_UNIT=", unit
);
1089 m4
= strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit
);
1090 sprintf(muid
, "_UID="UID_FMT
, uid
);
1093 /* Look for messages from the user service itself */
1094 (r
= sd_journal_add_match(j
, m1
, 0)) ||
1095 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1097 /* Look for messages from systemd about this service */
1098 (r
= sd_journal_add_disjunction(j
)) ||
1099 (r
= sd_journal_add_match(j
, m2
, 0)) ||
1100 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1102 /* Look for coredumps of the service */
1103 (r
= sd_journal_add_disjunction(j
)) ||
1104 (r
= sd_journal_add_match(j
, m3
, 0)) ||
1105 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1106 (r
= sd_journal_add_match(j
, "_UID=0", 0)) ||
1108 /* Look for messages from authorized daemons about this service */
1109 (r
= sd_journal_add_disjunction(j
)) ||
1110 (r
= sd_journal_add_match(j
, m4
, 0)) ||
1111 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1112 (r
= sd_journal_add_match(j
, "_UID=0", 0))
1115 if (r
== 0 && endswith(unit
, ".slice")) {
1116 char *m5
= strappend("_SYSTEMD_SLICE=", unit
);
1118 /* Show all messages belonging to a slice */
1120 (r
= sd_journal_add_disjunction(j
)) ||
1121 (r
= sd_journal_add_match(j
, m5
, 0)) ||
1122 (r
= sd_journal_add_match(j
, muid
, 0))
1129 static int get_boot_id_for_machine(const char *machine
, sd_id128_t
*boot_id
) {
1130 _cleanup_close_pair_
int pair
[2] = { -1, -1 };
1131 _cleanup_close_
int pidnsfd
= -1, mntnsfd
= -1, rootfd
= -1;
1141 if (!machine_name_is_valid(machine
))
1144 r
= container_get_leader(machine
, &pid
);
1148 r
= namespace_open(pid
, &pidnsfd
, &mntnsfd
, NULL
, NULL
, &rootfd
);
1152 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, pair
) < 0)
1162 pair
[0] = safe_close(pair
[0]);
1164 r
= namespace_enter(pidnsfd
, mntnsfd
, -1, -1, rootfd
);
1166 _exit(EXIT_FAILURE
);
1168 fd
= open("/proc/sys/kernel/random/boot_id", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1170 _exit(EXIT_FAILURE
);
1172 r
= loop_read_exact(fd
, buf
, 36, false);
1175 _exit(EXIT_FAILURE
);
1177 k
= send(pair
[1], buf
, 36, MSG_NOSIGNAL
);
1179 _exit(EXIT_FAILURE
);
1181 _exit(EXIT_SUCCESS
);
1184 pair
[1] = safe_close(pair
[1]);
1186 r
= wait_for_terminate(child
, &si
);
1187 if (r
< 0 || si
.si_code
!= CLD_EXITED
|| si
.si_status
!= EXIT_SUCCESS
)
1188 return r
< 0 ? r
: -EIO
;
1190 k
= recv(pair
[0], buf
, 36, 0);
1195 r
= sd_id128_from_string(buf
, boot_id
);
1202 int add_match_this_boot(sd_journal
*j
, const char *machine
) {
1203 char match
[9+32+1] = "_BOOT_ID=";
1210 r
= get_boot_id_for_machine(machine
, &boot_id
);
1212 return log_error_errno(r
, "Failed to get boot id of container %s: %m", machine
);
1214 r
= sd_id128_get_boot(&boot_id
);
1216 return log_error_errno(r
, "Failed to get boot id: %m");
1219 sd_id128_to_string(boot_id
, match
+ 9);
1220 r
= sd_journal_add_match(j
, match
, strlen(match
));
1222 return log_error_errno(r
, "Failed to add match: %m");
1224 r
= sd_journal_add_conjunction(j
);
1226 return log_error_errno(r
, "Failed to add conjunction: %m");
1231 int show_journal_by_unit(
1240 int journal_open_flags
,
1244 _cleanup_journal_close_ sd_journal
*j
= NULL
;
1248 assert(mode
< _OUTPUT_MODE_MAX
);
1254 r
= sd_journal_open(&j
, journal_open_flags
);
1256 return log_error_errno(r
, "Failed to open journal: %m");
1258 r
= add_match_this_boot(j
, NULL
);
1263 r
= add_matches_for_unit(j
, unit
);
1265 r
= add_matches_for_user_unit(j
, unit
, uid
);
1267 return log_error_errno(r
, "Failed to add unit matches: %m");
1269 if (_unlikely_(log_get_max_level() >= LOG_DEBUG
)) {
1270 _cleanup_free_
char *filter
;
1272 filter
= journal_make_match_string(j
);
1276 log_debug("Journal filter: %s", filter
);
1279 return show_journal(f
, j
, mode
, n_columns
, not_before
, how_many
, flags
, ellipsized
);
1282 static const char *const output_mode_table
[_OUTPUT_MODE_MAX
] = {
1283 [OUTPUT_SHORT
] = "short",
1284 [OUTPUT_SHORT_ISO
] = "short-iso",
1285 [OUTPUT_SHORT_PRECISE
] = "short-precise",
1286 [OUTPUT_SHORT_MONOTONIC
] = "short-monotonic",
1287 [OUTPUT_VERBOSE
] = "verbose",
1288 [OUTPUT_EXPORT
] = "export",
1289 [OUTPUT_JSON
] = "json",
1290 [OUTPUT_JSON_PRETTY
] = "json-pretty",
1291 [OUTPUT_JSON_SSE
] = "json-sse",
1292 [OUTPUT_CAT
] = "cat"
1295 DEFINE_STRING_TABLE_LOOKUP(output_mode
, OutputMode
);