]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/logs-show.c
2 This file is part of systemd.
4 Copyright 2012 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/socket.h>
32 #include "sd-journal.h"
34 #include "alloc-util.h"
36 #include "formats-util.h"
38 #include "hostname-util.h"
40 #include "journal-internal.h"
42 #include "logs-show.h"
44 #include "output-mode.h"
45 #include "parse-util.h"
46 #include "process-util.h"
47 #include "sparse-endian.h"
48 #include "stdio-util.h"
49 #include "string-table.h"
50 #include "string-util.h"
51 #include "terminal-util.h"
52 #include "time-util.h"
56 /* up to three lines (each up to 100 characters) or 300 characters, whichever is less */
57 #define PRINT_LINE_THRESHOLD 3
58 #define PRINT_CHAR_THRESHOLD 300
60 #define JSON_THRESHOLD 4096
62 static int print_catalog(FILE *f
, sd_journal
*j
) {
64 _cleanup_free_
char *t
= NULL
, *z
= NULL
;
67 r
= sd_journal_get_catalog(j
, &t
);
71 z
= strreplace(strstrip(t
), "\n", "\n-- ");
82 static int parse_field(const void *data
, size_t length
, const char *field
, char **target
, size_t *target_size
) {
94 if (memcmp(data
, field
, fl
))
98 buf
= new(char, nl
+1);
102 memcpy(buf
, (const char*) data
+ fl
, nl
);
114 static bool shall_print(const char *p
, size_t l
, OutputFlags flags
) {
117 if (flags
& OUTPUT_SHOW_ALL
)
120 if (l
>= PRINT_CHAR_THRESHOLD
)
123 if (!utf8_is_printable(p
, l
))
129 static bool print_multiline(FILE *f
, unsigned prefix
, unsigned n_columns
, OutputFlags flags
, int priority
, const char* message
, size_t message_len
) {
130 const char *color_on
= "", *color_off
= "";
131 const char *pos
, *end
;
132 bool ellipsized
= false;
135 if (flags
& OUTPUT_COLOR
) {
136 if (priority
<= LOG_ERR
) {
137 color_on
= ANSI_HIGHLIGHT_RED
;
138 color_off
= ANSI_NORMAL
;
139 } else if (priority
<= LOG_NOTICE
) {
140 color_on
= ANSI_HIGHLIGHT
;
141 color_off
= ANSI_NORMAL
;
145 /* A special case: make sure that we print a newline when
146 the message is empty. */
147 if (message_len
== 0)
151 pos
< message
+ message_len
;
152 pos
= end
+ 1, line
++) {
153 bool continuation
= line
> 0;
156 for (end
= pos
; end
< message
+ message_len
&& *end
!= '\n'; end
++)
161 /* We need to figure out when we are showing not-last line, *and*
162 * will skip subsequent lines. In that case, we will put the dots
163 * at the end of the line, instead of putting dots in the middle
167 line
+ 1 == PRINT_LINE_THRESHOLD
||
168 end
+ 1 >= message
+ PRINT_CHAR_THRESHOLD
;
170 if (flags
& (OUTPUT_FULL_WIDTH
| OUTPUT_SHOW_ALL
) ||
171 (prefix
+ len
+ 1 < n_columns
&& !tail_line
)) {
172 fprintf(f
, "%*s%s%.*s%s\n",
173 continuation
* prefix
, "",
174 color_on
, len
, pos
, color_off
);
178 /* Beyond this point, ellipsization will happen. */
181 if (prefix
< n_columns
&& n_columns
- prefix
>= 3) {
182 if (n_columns
- prefix
> (unsigned) len
+ 3)
183 fprintf(f
, "%*s%s%.*s...%s\n",
184 continuation
* prefix
, "",
185 color_on
, len
, pos
, color_off
);
187 _cleanup_free_
char *e
;
189 e
= ellipsize_mem(pos
, len
, n_columns
- prefix
,
190 tail_line
? 100 : 90);
192 fprintf(f
, "%*s%s%.*s%s\n",
193 continuation
* prefix
, "",
194 color_on
, len
, pos
, color_off
);
196 fprintf(f
, "%*s%s%s%s\n",
197 continuation
* prefix
, "",
198 color_on
, e
, color_off
);
210 static int output_timestamp_monotonic(FILE *f
, sd_journal
*j
, const char *monotonic
) {
220 r
= safe_atou64(monotonic
, &t
);
222 r
= sd_journal_get_monotonic_usec(j
, &t
, &boot_id
);
224 return log_error_errno(r
, "Failed to get monotonic timestamp: %m");
226 fprintf(f
, "[%5llu.%06llu]",
227 (unsigned long long) (t
/ USEC_PER_SEC
),
228 (unsigned long long) (t
% USEC_PER_SEC
));
230 return 1 + 5 + 1 + 6 + 1;
233 static int output_timestamp_realtime(FILE *f
, sd_journal
*j
, OutputMode mode
, OutputFlags flags
, const char *realtime
) {
234 char buf
[MAX(FORMAT_TIMESTAMP_MAX
, 64)];
235 struct tm
*(*gettime_r
)(const time_t *, struct tm
*);
246 r
= safe_atou64(realtime
, &x
);
248 r
= sd_journal_get_realtime_usec(j
, &x
);
250 return log_error_errno(r
, "Failed to get realtime timestamp: %m");
252 if (mode
== OUTPUT_SHORT_FULL
) {
255 if (flags
& OUTPUT_UTC
)
256 k
= format_timestamp_utc(buf
, sizeof(buf
), x
);
258 k
= format_timestamp(buf
, sizeof(buf
), x
);
260 log_error("Failed to format timestamp.");
265 gettime_r
= (flags
& OUTPUT_UTC
) ? gmtime_r
: localtime_r
;
266 t
= (time_t) (x
/ USEC_PER_SEC
);
270 case OUTPUT_SHORT_UNIX
:
271 xsprintf(buf
, "%10llu.%06llu", (unsigned long long) t
, (unsigned long long) (x
% USEC_PER_SEC
));
274 case OUTPUT_SHORT_ISO
:
275 if (strftime(buf
, sizeof(buf
), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t
, &tm
)) <= 0) {
276 log_error("Failed for format ISO time");
282 case OUTPUT_SHORT_PRECISE
:
284 if (strftime(buf
, sizeof(buf
), "%b %d %H:%M:%S", gettime_r(&t
, &tm
)) <= 0) {
285 log_error("Failed to format syslog time");
289 if (mode
== OUTPUT_SHORT_PRECISE
) {
292 assert(sizeof(buf
) > strlen(buf
));
293 k
= sizeof(buf
) - strlen(buf
);
295 r
= snprintf(buf
+ strlen(buf
), k
, ".%06llu", (unsigned long long) (x
% USEC_PER_SEC
));
296 if (r
<= 0 || (size_t) r
>= k
) { /* too long? */
297 log_error("Failed to format precise time");
304 assert_not_reached("Unknown time format");
309 return (int) strlen(buf
);
312 static int output_short(
323 _cleanup_free_
char *hostname
= NULL
, *identifier
= NULL
, *comm
= NULL
, *pid
= NULL
, *fake_pid
= NULL
, *message
= NULL
, *realtime
= NULL
, *monotonic
= NULL
, *priority
= NULL
;
324 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;
326 bool ellipsized
= false;
331 /* Set the threshold to one bigger than the actual print
332 * threshold, so that if the line is actually longer than what
333 * we're willing to print, ellipsization will occur. This way
334 * we won't output a misleading line without any indication of
337 sd_journal_set_data_threshold(j
, flags
& (OUTPUT_SHOW_ALL
|OUTPUT_FULL_WIDTH
) ? 0 : PRINT_CHAR_THRESHOLD
+ 1);
339 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
341 r
= parse_field(data
, length
, "PRIORITY=", &priority
, &priority_len
);
347 r
= parse_field(data
, length
, "_HOSTNAME=", &hostname
, &hostname_len
);
353 r
= parse_field(data
, length
, "SYSLOG_IDENTIFIER=", &identifier
, &identifier_len
);
359 r
= parse_field(data
, length
, "_COMM=", &comm
, &comm_len
);
365 r
= parse_field(data
, length
, "_PID=", &pid
, &pid_len
);
371 r
= parse_field(data
, length
, "SYSLOG_PID=", &fake_pid
, &fake_pid_len
);
377 r
= parse_field(data
, length
, "_SOURCE_REALTIME_TIMESTAMP=", &realtime
, &realtime_len
);
383 r
= parse_field(data
, length
, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic
, &monotonic_len
);
389 r
= parse_field(data
, length
, "MESSAGE=", &message
, &message_len
);
394 log_debug_errno(r
, "Skipping message we can't read: %m");
398 return log_error_errno(r
, "Failed to get journal fields: %m");
401 log_debug("Skipping message without MESSAGE= field.");
405 if (!(flags
& OUTPUT_SHOW_ALL
))
406 strip_tab_ansi(&message
, &message_len
);
408 if (priority_len
== 1 && *priority
>= '0' && *priority
<= '7')
411 if (mode
== OUTPUT_SHORT_MONOTONIC
)
412 r
= output_timestamp_monotonic(f
, j
, monotonic
);
414 r
= output_timestamp_realtime(f
, j
, mode
, flags
, realtime
);
419 if (flags
& OUTPUT_NO_HOSTNAME
) {
420 /* Suppress display of the hostname if this is requested. */
421 hostname
= mfree(hostname
);
425 if (hostname
&& shall_print(hostname
, hostname_len
, flags
)) {
426 fprintf(f
, " %.*s", (int) hostname_len
, hostname
);
427 n
+= hostname_len
+ 1;
430 if (identifier
&& shall_print(identifier
, identifier_len
, flags
)) {
431 fprintf(f
, " %.*s", (int) identifier_len
, identifier
);
432 n
+= identifier_len
+ 1;
433 } else if (comm
&& shall_print(comm
, comm_len
, flags
)) {
434 fprintf(f
, " %.*s", (int) comm_len
, comm
);
437 fputs(" unknown", f
);
439 if (pid
&& shall_print(pid
, pid_len
, flags
)) {
440 fprintf(f
, "[%.*s]", (int) pid_len
, pid
);
442 } else if (fake_pid
&& shall_print(fake_pid
, fake_pid_len
, flags
)) {
443 fprintf(f
, "[%.*s]", (int) fake_pid_len
, fake_pid
);
444 n
+= fake_pid_len
+ 2;
447 if (!(flags
& OUTPUT_SHOW_ALL
) && !utf8_is_printable(message
, message_len
)) {
448 char bytes
[FORMAT_BYTES_MAX
];
449 fprintf(f
, ": [%s blob data]\n", format_bytes(bytes
, sizeof(bytes
), message_len
));
453 print_multiline(f
, n
+ 2, n_columns
, flags
, p
, message
, message_len
);
456 if (flags
& OUTPUT_CATALOG
)
462 static int output_verbose(
471 _cleanup_free_
char *cursor
= NULL
;
472 uint64_t realtime
= 0;
473 char ts
[FORMAT_TIMESTAMP_MAX
+ 7];
479 sd_journal_set_data_threshold(j
, 0);
481 r
= sd_journal_get_data(j
, "_SOURCE_REALTIME_TIMESTAMP", &data
, &length
);
483 log_debug("Source realtime timestamp not found");
485 return log_full_errno(r
== -EADDRNOTAVAIL
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get source realtime timestamp: %m");
487 _cleanup_free_
char *value
= NULL
;
489 r
= parse_field(data
, length
, "_SOURCE_REALTIME_TIMESTAMP=", &value
, NULL
);
494 r
= safe_atou64(value
, &realtime
);
496 log_debug_errno(r
, "Failed to parse realtime timestamp: %m");
500 r
= sd_journal_get_realtime_usec(j
, &realtime
);
502 return log_full_errno(r
== -EADDRNOTAVAIL
? LOG_DEBUG
: LOG_ERR
, r
, "Failed to get realtime timestamp: %m");
505 r
= sd_journal_get_cursor(j
, &cursor
);
507 return log_error_errno(r
, "Failed to get cursor: %m");
509 fprintf(f
, "%s [%s]\n",
511 format_timestamp_us_utc(ts
, sizeof(ts
), realtime
) :
512 format_timestamp_us(ts
, sizeof(ts
), realtime
),
515 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
518 const char *on
= "", *off
= "";
520 c
= memchr(data
, '=', length
);
522 log_error("Invalid field.");
525 fieldlen
= c
- (const char*) data
;
527 if (flags
& OUTPUT_COLOR
&& startswith(data
, "MESSAGE=")) {
532 if ((flags
& OUTPUT_SHOW_ALL
) ||
533 (((length
< PRINT_CHAR_THRESHOLD
) || flags
& OUTPUT_FULL_WIDTH
)
534 && utf8_is_printable(data
, length
))) {
535 fprintf(f
, " %s%.*s=", on
, fieldlen
, (const char*)data
);
536 print_multiline(f
, 4 + fieldlen
+ 1, 0, OUTPUT_FULL_WIDTH
, 0, c
+ 1, length
- fieldlen
- 1);
539 char bytes
[FORMAT_BYTES_MAX
];
541 fprintf(f
, " %s%.*s=[%s blob data]%s\n",
543 (int) (c
- (const char*) data
),
545 format_bytes(bytes
, sizeof(bytes
), length
- (c
- (const char *) data
) - 1),
553 if (flags
& OUTPUT_CATALOG
)
559 static int output_export(
569 usec_t realtime
, monotonic
;
570 _cleanup_free_
char *cursor
= NULL
;
576 sd_journal_set_data_threshold(j
, 0);
578 r
= sd_journal_get_realtime_usec(j
, &realtime
);
580 return log_error_errno(r
, "Failed to get realtime timestamp: %m");
582 r
= sd_journal_get_monotonic_usec(j
, &monotonic
, &boot_id
);
584 return log_error_errno(r
, "Failed to get monotonic timestamp: %m");
586 r
= sd_journal_get_cursor(j
, &cursor
);
588 return log_error_errno(r
, "Failed to get cursor: %m");
592 "__REALTIME_TIMESTAMP="USEC_FMT
"\n"
593 "__MONOTONIC_TIMESTAMP="USEC_FMT
"\n"
598 sd_id128_to_string(boot_id
, sid
));
600 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
602 /* We already printed the boot id, from the data in
603 * the header, hence let's suppress it here */
605 startswith(data
, "_BOOT_ID="))
608 if (utf8_is_printable_newline(data
, length
, false))
609 fwrite(data
, length
, 1, f
);
614 c
= memchr(data
, '=', length
);
616 log_error("Invalid field.");
620 fwrite(data
, c
- (const char*) data
, 1, f
);
622 le64
= htole64(length
- (c
- (const char*) data
) - 1);
623 fwrite(&le64
, sizeof(le64
), 1, f
);
624 fwrite(c
+ 1, length
- (c
- (const char*) data
) - 1, 1, f
);
647 if (!(flags
& OUTPUT_SHOW_ALL
) && l
>= JSON_THRESHOLD
)
650 else if (!(flags
& OUTPUT_SHOW_ALL
) && !utf8_is_printable(p
, l
)) {
651 bool not_first
= false;
657 fprintf(f
, ", %u", (uint8_t) *p
);
660 fprintf(f
, "%u", (uint8_t) *p
);
672 if (*p
== '"' || *p
== '\\') {
675 } else if (*p
== '\n')
677 else if ((uint8_t) *p
< ' ')
678 fprintf(f
, "\\u%04x", (uint8_t) *p
);
690 static int output_json(
697 uint64_t realtime
, monotonic
;
698 _cleanup_free_
char *cursor
= NULL
;
705 bool done
, separator
;
709 sd_journal_set_data_threshold(j
, flags
& OUTPUT_SHOW_ALL
? 0 : JSON_THRESHOLD
);
711 r
= sd_journal_get_realtime_usec(j
, &realtime
);
713 return log_error_errno(r
, "Failed to get realtime timestamp: %m");
715 r
= sd_journal_get_monotonic_usec(j
, &monotonic
, &boot_id
);
717 return log_error_errno(r
, "Failed to get monotonic timestamp: %m");
719 r
= sd_journal_get_cursor(j
, &cursor
);
721 return log_error_errno(r
, "Failed to get cursor: %m");
723 if (mode
== OUTPUT_JSON_PRETTY
)
726 "\t\"__CURSOR\" : \"%s\",\n"
727 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT
"\",\n"
728 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT
"\",\n"
729 "\t\"_BOOT_ID\" : \"%s\"",
733 sd_id128_to_string(boot_id
, sid
));
735 if (mode
== OUTPUT_JSON_SSE
)
739 "{ \"__CURSOR\" : \"%s\", "
740 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT
"\", "
741 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT
"\", "
742 "\"_BOOT_ID\" : \"%s\"",
746 sd_id128_to_string(boot_id
, sid
));
749 h
= hashmap_new(&string_hash_ops
);
753 /* First round, iterate through the entry and count how often each field appears */
754 JOURNAL_FOREACH_DATA_RETVAL(j
, data
, length
, r
) {
760 memcmp(data
, "_BOOT_ID=", 9) == 0)
763 eq
= memchr(data
, '=', length
);
767 n
= strndup(data
, eq
- (const char*) data
);
773 u
= PTR_TO_UINT(hashmap_get(h
, n
));
775 r
= hashmap_put(h
, n
, UINT_TO_PTR(1));
782 r
= hashmap_update(h
, n
, UINT_TO_PTR(u
+ 1));
798 SD_JOURNAL_FOREACH_DATA(j
, data
, length
) {
804 /* We already printed the boot id, from the data in
805 * the header, hence let's suppress it here */
807 memcmp(data
, "_BOOT_ID=", 9) == 0)
810 eq
= memchr(data
, '=', length
);
815 if (mode
== OUTPUT_JSON_PRETTY
)
821 m
= eq
- (const char*) data
;
823 n
= strndup(data
, m
);
829 u
= PTR_TO_UINT(hashmap_get2(h
, n
, (void**) &kk
));
831 /* We already printed this, let's jump to the next */
837 /* Field only appears once, output it directly */
839 json_escape(f
, data
, m
, flags
);
842 json_escape(f
, eq
+ 1, length
- m
- 1, flags
);
844 hashmap_remove(h
, n
);
853 /* Field appears multiple times, output it as array */
854 json_escape(f
, data
, m
, flags
);
856 json_escape(f
, eq
+ 1, length
- m
- 1, flags
);
858 /* Iterate through the end of the list */
860 while (sd_journal_enumerate_data(j
, &data
, &length
) > 0) {
864 if (memcmp(data
, n
, m
) != 0)
867 if (((const char*) data
)[m
] != '=')
871 json_escape(f
, (const char*) data
+ m
+ 1, length
- m
- 1, flags
);
876 hashmap_remove(h
, n
);
880 /* Iterate data fields form the beginning */
890 if (mode
== OUTPUT_JSON_PRETTY
)
892 else if (mode
== OUTPUT_JSON_SSE
)
900 while ((k
= hashmap_steal_first_key(h
)))
908 static int output_cat(
922 sd_journal_set_data_threshold(j
, 0);
924 r
= sd_journal_get_data(j
, "MESSAGE", &data
, &l
);
926 /* An entry without MESSAGE=? */
930 return log_error_errno(r
, "Failed to get data: %m");
935 fwrite((const char*) data
+ 8, 1, l
- 8, f
);
941 static int (*output_funcs
[_OUTPUT_MODE_MAX
])(
946 OutputFlags flags
) = {
948 [OUTPUT_SHORT
] = output_short
,
949 [OUTPUT_SHORT_ISO
] = output_short
,
950 [OUTPUT_SHORT_PRECISE
] = output_short
,
951 [OUTPUT_SHORT_MONOTONIC
] = output_short
,
952 [OUTPUT_SHORT_UNIX
] = output_short
,
953 [OUTPUT_SHORT_FULL
] = output_short
,
954 [OUTPUT_VERBOSE
] = output_verbose
,
955 [OUTPUT_EXPORT
] = output_export
,
956 [OUTPUT_JSON
] = output_json
,
957 [OUTPUT_JSON_PRETTY
] = output_json
,
958 [OUTPUT_JSON_SSE
] = output_json
,
959 [OUTPUT_CAT
] = output_cat
972 assert(mode
< _OUTPUT_MODE_MAX
);
975 n_columns
= columns();
977 ret
= output_funcs
[mode
](f
, j
, mode
, n_columns
, flags
);
980 if (ellipsized
&& ret
> 0)
986 static int maybe_print_begin_newline(FILE *f
, OutputFlags
*flags
) {
990 if (!(*flags
& OUTPUT_BEGIN_NEWLINE
))
993 /* Print a beginning new line if that's request, but only once
994 * on the first line we print. */
997 *flags
&= ~OUTPUT_BEGIN_NEWLINE
;
1001 static int show_journal(FILE *f
,
1012 bool need_seek
= false;
1013 int warn_cutoff
= flags
& OUTPUT_WARN_CUTOFF
;
1017 assert(mode
< _OUTPUT_MODE_MAX
);
1020 r
= sd_journal_seek_tail(j
);
1022 return log_error_errno(r
, "Failed to seek to tail: %m");
1024 r
= sd_journal_previous_skip(j
, how_many
);
1026 return log_error_errno(r
, "Failed to skip previous: %m");
1033 r
= sd_journal_next(j
);
1035 return log_error_errno(r
, "Failed to iterate through journal: %m");
1043 if (not_before
> 0) {
1044 r
= sd_journal_get_monotonic_usec(j
, &usec
, NULL
);
1046 /* -ESTALE is returned if the
1047 timestamp is not from this boot */
1051 return log_error_errno(r
, "Failed to get journal time: %m");
1053 if (usec
< not_before
)
1058 maybe_print_begin_newline(f
, &flags
);
1060 r
= output_journal(f
, j
, mode
, n_columns
, flags
, ellipsized
);
1065 if (warn_cutoff
&& line
< how_many
&& not_before
> 0) {
1069 /* Check whether the cutoff line is too early */
1071 r
= sd_id128_get_boot(&boot_id
);
1073 return log_error_errno(r
, "Failed to get boot id: %m");
1075 r
= sd_journal_get_cutoff_monotonic_usec(j
, boot_id
, &cutoff
, NULL
);
1077 return log_error_errno(r
, "Failed to get journal cutoff time: %m");
1079 if (r
> 0 && not_before
< cutoff
) {
1080 maybe_print_begin_newline(f
, &flags
);
1081 fprintf(f
, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1084 warn_cutoff
= false;
1087 if (!(flags
& OUTPUT_FOLLOW
))
1090 r
= sd_journal_wait(j
, USEC_INFINITY
);
1092 return log_error_errno(r
, "Failed to wait for journal: %m");
1099 int add_matches_for_unit(sd_journal
*j
, const char *unit
) {
1100 const char *m1
, *m2
, *m3
, *m4
;
1106 m1
= strjoina("_SYSTEMD_UNIT=", unit
);
1107 m2
= strjoina("COREDUMP_UNIT=", unit
);
1108 m3
= strjoina("UNIT=", unit
);
1109 m4
= strjoina("OBJECT_SYSTEMD_UNIT=", unit
);
1112 /* Look for messages from the service itself */
1113 (r
= sd_journal_add_match(j
, m1
, 0)) ||
1115 /* Look for coredumps of the service */
1116 (r
= sd_journal_add_disjunction(j
)) ||
1117 (r
= sd_journal_add_match(j
, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1118 (r
= sd_journal_add_match(j
, "_UID=0", 0)) ||
1119 (r
= sd_journal_add_match(j
, m2
, 0)) ||
1121 /* Look for messages from PID 1 about this service */
1122 (r
= sd_journal_add_disjunction(j
)) ||
1123 (r
= sd_journal_add_match(j
, "_PID=1", 0)) ||
1124 (r
= sd_journal_add_match(j
, m3
, 0)) ||
1126 /* Look for messages from authorized daemons about this service */
1127 (r
= sd_journal_add_disjunction(j
)) ||
1128 (r
= sd_journal_add_match(j
, "_UID=0", 0)) ||
1129 (r
= sd_journal_add_match(j
, m4
, 0))
1132 if (r
== 0 && endswith(unit
, ".slice")) {
1135 m5
= strjoina("_SYSTEMD_SLICE=", unit
);
1137 /* Show all messages belonging to a slice */
1139 (r
= sd_journal_add_disjunction(j
)) ||
1140 (r
= sd_journal_add_match(j
, m5
, 0))
1147 int add_matches_for_user_unit(sd_journal
*j
, const char *unit
, uid_t uid
) {
1149 char *m1
, *m2
, *m3
, *m4
;
1150 char muid
[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t
)];
1155 m1
= strjoina("_SYSTEMD_USER_UNIT=", unit
);
1156 m2
= strjoina("USER_UNIT=", unit
);
1157 m3
= strjoina("COREDUMP_USER_UNIT=", unit
);
1158 m4
= strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit
);
1159 sprintf(muid
, "_UID="UID_FMT
, uid
);
1162 /* Look for messages from the user service itself */
1163 (r
= sd_journal_add_match(j
, m1
, 0)) ||
1164 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1166 /* Look for messages from systemd about this service */
1167 (r
= sd_journal_add_disjunction(j
)) ||
1168 (r
= sd_journal_add_match(j
, m2
, 0)) ||
1169 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1171 /* Look for coredumps of the service */
1172 (r
= sd_journal_add_disjunction(j
)) ||
1173 (r
= sd_journal_add_match(j
, m3
, 0)) ||
1174 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1175 (r
= sd_journal_add_match(j
, "_UID=0", 0)) ||
1177 /* Look for messages from authorized daemons about this service */
1178 (r
= sd_journal_add_disjunction(j
)) ||
1179 (r
= sd_journal_add_match(j
, m4
, 0)) ||
1180 (r
= sd_journal_add_match(j
, muid
, 0)) ||
1181 (r
= sd_journal_add_match(j
, "_UID=0", 0))
1184 if (r
== 0 && endswith(unit
, ".slice")) {
1187 m5
= strjoina("_SYSTEMD_SLICE=", unit
);
1189 /* Show all messages belonging to a slice */
1191 (r
= sd_journal_add_disjunction(j
)) ||
1192 (r
= sd_journal_add_match(j
, m5
, 0)) ||
1193 (r
= sd_journal_add_match(j
, muid
, 0))
1200 static int get_boot_id_for_machine(const char *machine
, sd_id128_t
*boot_id
) {
1201 _cleanup_close_pair_
int pair
[2] = { -1, -1 };
1202 _cleanup_close_
int pidnsfd
= -1, mntnsfd
= -1, rootfd
= -1;
1212 if (!machine_name_is_valid(machine
))
1215 r
= container_get_leader(machine
, &pid
);
1219 r
= namespace_open(pid
, &pidnsfd
, &mntnsfd
, NULL
, NULL
, &rootfd
);
1223 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, pair
) < 0)
1233 pair
[0] = safe_close(pair
[0]);
1235 r
= namespace_enter(pidnsfd
, mntnsfd
, -1, -1, rootfd
);
1237 _exit(EXIT_FAILURE
);
1239 fd
= open("/proc/sys/kernel/random/boot_id", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1241 _exit(EXIT_FAILURE
);
1243 r
= loop_read_exact(fd
, buf
, 36, false);
1246 _exit(EXIT_FAILURE
);
1248 k
= send(pair
[1], buf
, 36, MSG_NOSIGNAL
);
1250 _exit(EXIT_FAILURE
);
1252 _exit(EXIT_SUCCESS
);
1255 pair
[1] = safe_close(pair
[1]);
1257 r
= wait_for_terminate(child
, &si
);
1258 if (r
< 0 || si
.si_code
!= CLD_EXITED
|| si
.si_status
!= EXIT_SUCCESS
)
1259 return r
< 0 ? r
: -EIO
;
1261 k
= recv(pair
[0], buf
, 36, 0);
1266 r
= sd_id128_from_string(buf
, boot_id
);
1273 int add_match_this_boot(sd_journal
*j
, const char *machine
) {
1274 char match
[9+32+1] = "_BOOT_ID=";
1281 r
= get_boot_id_for_machine(machine
, &boot_id
);
1283 return log_error_errno(r
, "Failed to get boot id of container %s: %m", machine
);
1285 r
= sd_id128_get_boot(&boot_id
);
1287 return log_error_errno(r
, "Failed to get boot id: %m");
1290 sd_id128_to_string(boot_id
, match
+ 9);
1291 r
= sd_journal_add_match(j
, match
, strlen(match
));
1293 return log_error_errno(r
, "Failed to add match: %m");
1295 r
= sd_journal_add_conjunction(j
);
1297 return log_error_errno(r
, "Failed to add conjunction: %m");
1302 int show_journal_by_unit(
1311 int journal_open_flags
,
1315 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
1319 assert(mode
< _OUTPUT_MODE_MAX
);
1325 r
= sd_journal_open(&j
, journal_open_flags
);
1327 return log_error_errno(r
, "Failed to open journal: %m");
1329 r
= add_match_this_boot(j
, NULL
);
1334 r
= add_matches_for_unit(j
, unit
);
1336 r
= add_matches_for_user_unit(j
, unit
, uid
);
1338 return log_error_errno(r
, "Failed to add unit matches: %m");
1340 if (_unlikely_(log_get_max_level() >= LOG_DEBUG
)) {
1341 _cleanup_free_
char *filter
;
1343 filter
= journal_make_match_string(j
);
1347 log_debug("Journal filter: %s", filter
);
1350 return show_journal(f
, j
, mode
, n_columns
, not_before
, how_many
, flags
, ellipsized
);