1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include <sys/inotify.h>
17 #include "sd-device.h"
18 #include "sd-journal.h"
21 #include "alloc-util.h"
23 #include "bus-error.h"
24 #include "bus-locator.h"
28 #include "chattr-util.h"
29 #include "constants.h"
30 #include "devnum-util.h"
31 #include "dirent-util.h"
32 #include "dissect-image.h"
35 #include "format-table.h"
36 #include "format-util.h"
39 #include "glob-util.h"
40 #include "hostname-util.h"
41 #include "id128-print.h"
43 #include "journal-def.h"
44 #include "journal-internal.h"
45 #include "journal-util.h"
46 #include "journal-vacuum.h"
47 #include "journal-verify.h"
48 #include "locale-util.h"
50 #include "logs-show.h"
51 #include "main-func.h"
52 #include "memory-util.h"
53 #include "memstream-util.h"
54 #include "missing_sched.h"
56 #include "mount-util.h"
57 #include "mountpoint-util.h"
58 #include "nulstr-util.h"
60 #include "parse-argument.h"
61 #include "parse-util.h"
62 #include "path-util.h"
63 #include "pcre2-util.h"
64 #include "pretty-print.h"
65 #include "qrcode-util.h"
66 #include "random-util.h"
67 #include "rlimit-util.h"
70 #include "signal-util.h"
71 #include "static-destruct.h"
72 #include "stdio-util.h"
73 #include "string-table.h"
75 #include "syslog-util.h"
76 #include "terminal-util.h"
77 #include "tmpfile-util.h"
78 #include "unit-name.h"
79 #include "user-util.h"
82 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
83 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
86 /* Special values for arg_lines */
87 ARG_LINES_DEFAULT
= -2,
91 static OutputMode arg_output
= OUTPUT_SHORT
;
92 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
93 static bool arg_utc
= false;
94 static bool arg_follow
= false;
95 static bool arg_full
= true;
96 static bool arg_all
= false;
97 static PagerFlags arg_pager_flags
= 0;
98 static int arg_lines
= ARG_LINES_DEFAULT
;
99 static bool arg_lines_oldest
= false;
100 static bool arg_no_tail
= false;
101 static bool arg_truncate_newline
= false;
102 static bool arg_quiet
= false;
103 static bool arg_merge
= false;
104 static bool arg_boot
= false;
105 static sd_id128_t arg_boot_id
= {};
106 static int arg_boot_offset
= 0;
107 static bool arg_dmesg
= false;
108 static bool arg_no_hostname
= false;
109 static const char *arg_cursor
= NULL
;
110 static const char *arg_cursor_file
= NULL
;
111 static const char *arg_after_cursor
= NULL
;
112 static bool arg_show_cursor
= false;
113 static const char *arg_directory
= NULL
;
114 static char **arg_file
= NULL
;
115 static bool arg_file_stdin
= false;
116 static int arg_priorities
= 0xFF;
117 static Set
*arg_facilities
= NULL
;
118 static char *arg_verify_key
= NULL
;
120 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
121 static bool arg_force
= false;
123 static usec_t arg_since
= 0, arg_until
= 0;
124 static bool arg_since_set
= false, arg_until_set
= false;
125 static char **arg_syslog_identifier
= NULL
;
126 static char **arg_exclude_identifier
= NULL
;
127 static char **arg_system_units
= NULL
;
128 static char **arg_user_units
= NULL
;
129 static const char *arg_field
= NULL
;
130 static bool arg_catalog
= false;
131 static bool arg_reverse
= false;
132 static int arg_journal_type
= 0;
133 static int arg_journal_additional_open_flags
= 0;
134 static int arg_namespace_flags
= 0;
135 static char *arg_root
= NULL
;
136 static char *arg_image
= NULL
;
137 static const char *arg_machine
= NULL
;
138 static const char *arg_namespace
= NULL
;
139 static uint64_t arg_vacuum_size
= 0;
140 static uint64_t arg_vacuum_n_files
= 0;
141 static usec_t arg_vacuum_time
= 0;
142 static Set
*arg_output_fields
= NULL
;
143 static const char *arg_pattern
= NULL
;
144 static pcre2_code
*arg_compiled_pattern
= NULL
;
145 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
146 ImagePolicy
*arg_image_policy
= NULL
;
148 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
151 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
152 STATIC_DESTRUCTOR_REGISTER(arg_exclude_identifier
, strv_freep
);
153 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
154 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
155 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
156 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
157 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
158 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
159 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
170 ACTION_UPDATE_CATALOG
,
173 ACTION_RELINQUISH_VAR
,
177 ACTION_ROTATE_AND_VACUUM
,
179 ACTION_LIST_FIELD_NAMES
,
180 ACTION_LIST_NAMESPACES
,
181 } arg_action
= ACTION_SHOW
;
183 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
184 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
192 if (!path_startswith(devpath
, "/dev/"))
193 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
194 "Devpath does not start with /dev/");
196 if (stat(devpath
, &st
) < 0)
197 return log_error_errno(errno
, "Couldn't stat file: %m");
199 r
= sd_device_new_from_stat_rdev(&device
, &st
);
201 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
203 for (d
= device
; d
; ) {
204 _cleanup_free_
char *match
= NULL
;
205 const char *subsys
, *sysname
, *devnode
;
208 r
= sd_device_get_subsystem(d
, &subsys
);
212 r
= sd_device_get_sysname(d
, &sysname
);
216 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
220 r
= sd_journal_add_match(j
, match
, 0);
222 return log_error_errno(r
, "Failed to add match: %m");
224 if (sd_device_get_devname(d
, &devnode
) >= 0) {
225 _cleanup_free_
char *match1
= NULL
;
227 r
= stat(devnode
, &st
);
229 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
231 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
235 r
= sd_journal_add_match(j
, match1
, 0);
237 return log_error_errno(r
, "Failed to add match: %m");
241 if (sd_device_get_parent(d
, &parent
) < 0)
247 r
= add_match_this_boot(j
, arg_machine
);
249 return log_error_errno(r
, "Failed to add match for the current boot: %m");
254 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
257 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
259 return format_timestamp(buf
, l
, t
);
262 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
263 sd_id128_t id
= SD_ID128_NULL
;
266 if (streq(x
, "all")) {
267 *boot_id
= SD_ID128_NULL
;
270 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
273 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
274 r
= sd_id128_from_string(t
, &id
);
276 x
+= SD_ID128_STRING_MAX
- 1;
278 if (!IN_SET(*x
, 0, '-', '+'))
282 r
= safe_atoi(x
, &off
);
287 r
= safe_atoi(x
, &off
);
301 static int parse_lines(const char *arg
, bool graceful
) {
305 assert(arg
|| graceful
);
310 if (streq(arg
, "all")) {
311 arg_lines
= ARG_LINES_ALL
;
315 l
= startswith(arg
, "+");
317 r
= safe_atoi(l
?: arg
, &n
);
318 if (r
< 0 || n
< 0) {
322 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse --lines='%s'.", arg
);
326 arg_lines_oldest
= l
;
332 arg_lines_oldest
= false;
336 static bool arg_lines_needs_seek_end(void) {
337 return arg_lines
>= 0 && !arg_lines_oldest
;
340 static int help_facilities(void) {
342 puts("Available facilities:");
344 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
345 _cleanup_free_
char *t
= NULL
;
347 if (log_facility_unshifted_to_string_alloc(i
, &t
))
355 static int help(void) {
356 _cleanup_free_
char *link
= NULL
;
359 pager_open(arg_pager_flags
);
361 r
= terminal_urlify_man("journalctl", "1", &link
);
365 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
366 "%5$sQuery the journal.%6$s\n\n"
367 "%3$sSource Options:%4$s\n"
368 " --system Show the system journal\n"
369 " --user Show the user journal for the current user\n"
370 " -M --machine=CONTAINER Operate on local container\n"
371 " -m --merge Show entries from all available journals\n"
372 " -D --directory=PATH Show journal files from directory\n"
373 " -i --file=PATH Show journal file\n"
374 " --root=PATH Operate on an alternate filesystem root\n"
375 " --image=PATH Operate on disk image as filesystem root\n"
376 " --image-policy=POLICY Specify disk image dissection policy\n"
377 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
378 "\n%3$sFiltering Options:%4$s\n"
379 " -S --since=DATE Show entries not older than the specified date\n"
380 " -U --until=DATE Show entries not newer than the specified date\n"
381 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
382 " --after-cursor=CURSOR Show entries after the specified cursor\n"
383 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
384 " -b --boot[=ID] Show current boot or the specified boot\n"
385 " -u --unit=UNIT Show logs from the specified unit\n"
386 " --user-unit=UNIT Show logs from the specified user unit\n"
387 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
388 " -T --exclude-identifier=STRING\n"
389 " Hide entries with the specified syslog identifier\n"
390 " -p --priority=RANGE Show entries with the specified priority\n"
391 " --facility=FACILITY... Show entries with the specified facilities\n"
392 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
393 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
394 " -k --dmesg Show kernel message log from the current boot\n"
395 "\n%3$sOutput Control Options:%4$s\n"
396 " -o --output=STRING Change journal output mode (short, short-precise,\n"
397 " short-iso, short-iso-precise, short-full,\n"
398 " short-monotonic, short-unix, verbose, export,\n"
399 " json, json-pretty, json-sse, json-seq, cat,\n"
401 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
402 " -n --lines[=[+]INTEGER] Number of journal entries to show\n"
403 " -r --reverse Show the newest entries first\n"
404 " --show-cursor Print the cursor after all the entries\n"
405 " --utc Express time in Coordinated Universal Time (UTC)\n"
406 " -x --catalog Add message explanations where available\n"
407 " --no-hostname Suppress output of hostname field\n"
408 " --no-full Ellipsize fields\n"
409 " -a --all Show all fields, including long and unprintable\n"
410 " -f --follow Follow the journal\n"
411 " --no-tail Show all lines, even in follow mode\n"
412 " --truncate-newline Truncate entries by first newline character\n"
413 " -q --quiet Do not show info messages and privilege warning\n"
414 "\n%3$sPager Control Options:%4$s\n"
415 " --no-pager Do not pipe output into a pager\n"
416 " -e --pager-end Immediately jump to the end in the pager\n"
417 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
418 " --interval=TIME Time interval for changing the FSS sealing key\n"
419 " --verify-key=KEY Specify FSS verification key\n"
420 " --force Override of the FSS key pair with --setup-keys\n"
421 "\n%3$sCommands:%4$s\n"
422 " -h --help Show this help text\n"
423 " --version Show package version\n"
424 " -N --fields List all field names currently used\n"
425 " -F --field=FIELD List all values that a specified field takes\n"
426 " --list-boots Show terse information about recorded boots\n"
427 " --disk-usage Show total disk usage of all journal files\n"
428 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
429 " --vacuum-files=INT Leave only the specified number of journal files\n"
430 " --vacuum-time=TIME Remove journal files older than specified time\n"
431 " --verify Verify journal file consistency\n"
432 " --sync Synchronize unwritten journal messages to disk\n"
433 " --relinquish-var Stop logging to disk, log to temporary file system\n"
434 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
435 " --flush Flush all journal data from /run into /var\n"
436 " --rotate Request immediate rotation of the journal files\n"
437 " --header Show journal header information\n"
438 " --list-catalog Show all message IDs in the catalog\n"
439 " --dump-catalog Show entries in the message catalog\n"
440 " --update-catalog Update the message catalog database\n"
441 " --setup-keys Generate a new FSS key pair\n"
442 "\nSee the %2$s for details.\n",
443 program_invocation_short_name
,
453 static int parse_argv(int argc
, char *argv
[]) {
488 ARG_SMART_RELINQUISH_VAR
,
490 ARG_TRUNCATE_NEWLINE
,
500 static const struct option options
[] = {
501 { "help", no_argument
, NULL
, 'h' },
502 { "version" , no_argument
, NULL
, ARG_VERSION
},
503 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
504 { "pager-end", no_argument
, NULL
, 'e' },
505 { "follow", no_argument
, NULL
, 'f' },
506 { "force", no_argument
, NULL
, ARG_FORCE
},
507 { "output", required_argument
, NULL
, 'o' },
508 { "all", no_argument
, NULL
, 'a' },
509 { "full", no_argument
, NULL
, 'l' },
510 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
511 { "lines", optional_argument
, NULL
, 'n' },
512 { "truncate-newline", no_argument
, NULL
, ARG_TRUNCATE_NEWLINE
},
513 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
514 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
515 { "quiet", no_argument
, NULL
, 'q' },
516 { "merge", no_argument
, NULL
, 'm' },
517 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
518 { "boot", optional_argument
, NULL
, 'b' },
519 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
520 { "dmesg", no_argument
, NULL
, 'k' },
521 { "system", no_argument
, NULL
, ARG_SYSTEM
},
522 { "user", no_argument
, NULL
, ARG_USER
},
523 { "directory", required_argument
, NULL
, 'D' },
524 { "file", required_argument
, NULL
, 'i' },
525 { "root", required_argument
, NULL
, ARG_ROOT
},
526 { "image", required_argument
, NULL
, ARG_IMAGE
},
527 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
528 { "header", no_argument
, NULL
, ARG_HEADER
},
529 { "identifier", required_argument
, NULL
, 't' },
530 { "exclude-identifier", required_argument
, NULL
, 'T' },
531 { "priority", required_argument
, NULL
, 'p' },
532 { "facility", required_argument
, NULL
, ARG_FACILITY
},
533 { "grep", required_argument
, NULL
, 'g' },
534 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
535 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
536 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
537 { "verify", no_argument
, NULL
, ARG_VERIFY
},
538 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
539 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
540 { "cursor", required_argument
, NULL
, 'c' },
541 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
542 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
543 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
544 { "since", required_argument
, NULL
, 'S' },
545 { "until", required_argument
, NULL
, 'U' },
546 { "unit", required_argument
, NULL
, 'u' },
547 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
548 { "field", required_argument
, NULL
, 'F' },
549 { "fields", no_argument
, NULL
, 'N' },
550 { "catalog", no_argument
, NULL
, 'x' },
551 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
552 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
553 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
554 { "reverse", no_argument
, NULL
, 'r' },
555 { "machine", required_argument
, NULL
, 'M' },
556 { "utc", no_argument
, NULL
, ARG_UTC
},
557 { "flush", no_argument
, NULL
, ARG_FLUSH
},
558 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
559 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
560 { "sync", no_argument
, NULL
, ARG_SYNC
},
561 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
562 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
563 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
564 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
565 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
566 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
567 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
568 { "list-namespaces", no_argument
, NULL
, ARG_LIST_NAMESPACES
},
577 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:T:u:NF:xrM:i:", options
, NULL
)) >= 0)
588 arg_pager_flags
|= PAGER_DISABLE
;
592 arg_pager_flags
|= PAGER_JUMP_TO_END
;
594 if (arg_lines
== ARG_LINES_DEFAULT
)
606 if (streq(optarg
, "help")) {
607 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
611 arg_output
= output_mode_from_string(optarg
);
613 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
615 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
618 if (OUTPUT_MODE_IS_JSON(arg_output
))
619 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
621 arg_json_format_flags
= JSON_FORMAT_OFF
;
638 r
= parse_lines(optarg
?: argv
[optind
], !optarg
);
641 if (r
> 0 && !optarg
)
650 case ARG_TRUNCATE_NEWLINE
:
651 arg_truncate_newline
= true;
655 arg_action
= ACTION_NEW_ID128
;
668 arg_boot_id
= SD_ID128_NULL
;
674 arg_boot_id
= SD_ID128_NULL
;
678 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
680 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
684 /* Hmm, no argument? Maybe the next
685 * word on the command line is
686 * supposed to be the argument? Let's
687 * see if there is one and is parsable
688 * as a boot descriptor... */
689 } else if (optind
< argc
) {
690 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
699 arg_action
= ACTION_LIST_BOOTS
;
703 arg_boot
= arg_dmesg
= true;
707 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
711 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
715 arg_machine
= optarg
;
719 if (streq(optarg
, "*")) {
720 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
721 arg_namespace
= NULL
;
722 } else if (startswith(optarg
, "+")) {
723 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
724 arg_namespace
= optarg
+ 1;
725 } else if (isempty(optarg
)) {
726 arg_namespace_flags
= 0;
727 arg_namespace
= NULL
;
729 arg_namespace_flags
= 0;
730 arg_namespace
= optarg
;
735 case ARG_LIST_NAMESPACES
:
736 arg_action
= ACTION_LIST_NAMESPACES
;
740 arg_directory
= optarg
;
744 if (streq(optarg
, "-"))
745 /* An undocumented feature: we can read journal files from STDIN. We don't document
746 * this though, since after all we only support this for mmap-able, seekable files, and
747 * not for example pipes which are probably the primary use case for reading things from
748 * STDIN. To avoid confusion we hence don't document this feature. */
749 arg_file_stdin
= true;
751 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
753 return log_error_errno(r
, "Failed to add paths: %m");
758 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
764 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
769 case ARG_IMAGE_POLICY
:
770 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
779 case ARG_CURSOR_FILE
:
780 arg_cursor_file
= optarg
;
783 case ARG_AFTER_CURSOR
:
784 arg_after_cursor
= optarg
;
787 case ARG_SHOW_CURSOR
:
788 arg_show_cursor
= true;
792 arg_action
= ACTION_PRINT_HEADER
;
796 arg_action
= ACTION_VERIFY
;
800 arg_action
= ACTION_DISK_USAGE
;
803 case ARG_VACUUM_SIZE
:
804 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
806 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
808 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
811 case ARG_VACUUM_FILES
:
812 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
814 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
816 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
819 case ARG_VACUUM_TIME
:
820 r
= parse_sec(optarg
, &arg_vacuum_time
);
822 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
824 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
833 arg_action
= ACTION_SETUP_KEYS
;
837 r
= free_and_strdup(&arg_verify_key
, optarg
);
840 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
841 * in ps or htop output. */
842 memset(optarg
, 'x', strlen(optarg
));
844 arg_action
= ACTION_VERIFY
;
849 r
= parse_sec(optarg
, &arg_interval
);
850 if (r
< 0 || arg_interval
<= 0)
851 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
852 "Failed to parse sealing key change interval: %s", optarg
);
859 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
860 "Compiled without forward-secure sealing support.");
866 dots
= strstr(optarg
, "..");
868 _cleanup_free_
char *a
= NULL
;
872 a
= strndup(optarg
, dots
- optarg
);
876 from
= log_level_from_string(a
);
877 to
= log_level_from_string(dots
+ 2);
879 if (from
< 0 || to
< 0)
880 return log_error_errno(from
< 0 ? from
: to
,
881 "Failed to parse log level range %s", optarg
);
886 for (i
= from
; i
<= to
; i
++)
887 arg_priorities
|= 1 << i
;
889 for (i
= to
; i
<= from
; i
++)
890 arg_priorities
|= 1 << i
;
896 p
= log_level_from_string(optarg
);
898 return log_error_errno(p
, "Unknown log level %s", optarg
);
902 for (i
= 0; i
<= p
; i
++)
903 arg_priorities
|= 1 << i
;
913 _cleanup_free_
char *fac
= NULL
;
916 r
= extract_first_word(&p
, &fac
, ",", 0);
918 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
922 if (streq(fac
, "help")) {
927 num
= log_facility_unshifted_from_string(fac
);
929 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
931 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
939 arg_pattern
= optarg
;
942 case ARG_CASE_SENSITIVE
:
944 r
= parse_boolean(optarg
);
946 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
947 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
949 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
954 r
= parse_timestamp(optarg
, &arg_since
);
956 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
957 "Failed to parse timestamp: %s", optarg
);
958 arg_since_set
= true;
962 r
= parse_timestamp(optarg
, &arg_until
);
964 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
965 "Failed to parse timestamp: %s", optarg
);
966 arg_until_set
= true;
970 r
= strv_extend(&arg_syslog_identifier
, optarg
);
976 r
= strv_extend(&arg_exclude_identifier
, optarg
);
982 r
= strv_extend(&arg_system_units
, optarg
);
988 r
= strv_extend(&arg_user_units
, optarg
);
994 arg_action
= ACTION_LIST_FIELDS
;
999 arg_action
= ACTION_LIST_FIELD_NAMES
;
1002 case ARG_NO_HOSTNAME
:
1003 arg_no_hostname
= true;
1010 case ARG_LIST_CATALOG
:
1011 arg_action
= ACTION_LIST_CATALOG
;
1014 case ARG_DUMP_CATALOG
:
1015 arg_action
= ACTION_DUMP_CATALOG
;
1018 case ARG_UPDATE_CATALOG
:
1019 arg_action
= ACTION_UPDATE_CATALOG
;
1031 arg_action
= ACTION_FLUSH
;
1034 case ARG_SMART_RELINQUISH_VAR
: {
1035 int root_mnt_id
, log_mnt_id
;
1037 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
1038 * if it's on the same mount as the root file system there's no point in
1039 * relinquishing access and we can leave journald write to it until the very last
1042 r
= path_get_mnt_id("/", &root_mnt_id
);
1044 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1046 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1048 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1049 else if (root_mnt_id
== log_mnt_id
) {
1050 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1053 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1059 case ARG_RELINQUISH_VAR
:
1060 arg_action
= ACTION_RELINQUISH_VAR
;
1064 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1068 arg_action
= ACTION_SYNC
;
1071 case ARG_OUTPUT_FIELDS
: {
1072 _cleanup_strv_free_
char **v
= NULL
;
1074 v
= strv_split(optarg
, ",");
1078 r
= set_put_strdupv(&arg_output_fields
, v
);
1088 assert_not_reached();
1092 arg_lines
= ARG_LINES_ALL
;
1094 if (arg_follow
&& !arg_since_set
&& arg_lines
== ARG_LINES_DEFAULT
)
1097 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1099 arg_boot_id
= SD_ID128_NULL
;
1100 arg_boot_offset
= 0;
1103 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1104 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1105 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1107 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1108 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1109 "--since= must be before --until=.");
1111 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_cursor_file
+ !!arg_since_set
> 1)
1112 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1113 "Please specify only one of --since=, --cursor=, --cursor-file=, and --after-cursor=.");
1115 if (arg_follow
&& arg_reverse
)
1116 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1117 "Please specify either --reverse or --follow, not both.");
1119 if (arg_lines
>= 0 && arg_lines_oldest
&& (arg_reverse
|| arg_follow
))
1120 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1121 "--lines=+N is unsupported when --reverse or --follow is specified.");
1123 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1124 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1125 "Extraneous arguments starting with '%s'",
1128 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1129 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1130 "Using --boot or --list-boots with --merge is not supported.");
1132 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1133 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1134 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1135 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1136 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1140 arg_system_units
= strv_free(arg_system_units
);
1144 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1148 /* When --grep is used along with --lines without '+', i.e. when we start from the end of the
1149 * journal, we don't know how many lines we can print. So we search backwards and count until
1150 * enough lines have been printed or we hit the head.
1151 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1152 * if that is specified. */
1153 if (arg_lines_needs_seek_end() && !arg_follow
)
1158 arg_journal_additional_open_flags
= SD_JOURNAL_ASSUME_IMMUTABLE
;
1163 static int add_matches(sd_journal
*j
, char **args
) {
1164 bool have_term
= false;
1168 STRV_FOREACH(i
, args
) {
1171 if (streq(*i
, "+")) {
1174 r
= sd_journal_add_disjunction(j
);
1177 } else if (path_is_absolute(*i
)) {
1178 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1181 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1183 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1185 if (lstat(p
, &st
) < 0)
1186 return log_error_errno(errno
, "Couldn't stat file: %m");
1188 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1189 if (executable_is_script(p
, &interpreter
) > 0) {
1190 _cleanup_free_
char *comm
= NULL
;
1192 r
= path_extract_filename(p
, &comm
);
1194 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1196 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1200 /* Append _EXE only if the interpreter is not a link.
1201 Otherwise, it might be outdated often. */
1202 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1203 t2
= strjoin("_EXE=", interpreter
);
1208 t
= strjoin("_EXE=", p
);
1213 r
= sd_journal_add_match(j
, t
, 0);
1216 r
= sd_journal_add_match(j
, t2
, 0);
1218 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1219 r
= add_matches_for_device(j
, p
);
1223 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1224 "File is neither a device node, nor regular file, nor executable: %s",
1229 r
= sd_journal_add_match(j
, *i
, 0);
1234 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1237 if (!strv_isempty(args
) && !have_term
)
1238 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1239 "\"+\" can only be used between terms");
1244 static int list_namespaces(const char *root
) {
1245 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1247 char machine_id
[SD_ID128_STRING_MAX
];
1250 r
= sd_id128_get_machine(&machine
);
1252 return log_error_errno(r
, "Failed to get machine ID: %m");
1254 sd_id128_to_string(machine
, machine_id
);
1256 table
= table_new("namespace");
1260 (void) table_set_sort(table
, (size_t) 0);
1262 FOREACH_STRING(dir
, "/var/log/journal", "/run/log/journal") {
1263 _cleanup_free_
char *path
= NULL
;
1264 _cleanup_closedir_
DIR *dirp
= NULL
;
1266 path
= path_join(root
, dir
);
1270 dirp
= opendir(path
);
1272 log_debug_errno(errno
, "Failed to open directory %s, ignoring: %m", path
);
1276 FOREACH_DIRENT(de
, dirp
, return log_error_errno(errno
, "Failed to iterate through %s: %m", path
)) {
1279 if (!startswith(de
->d_name
, machine_id
))
1282 dot
= strchr(de
->d_name
, '.');
1286 if (!log_namespace_name_valid(dot
+ 1))
1289 r
= table_add_cell(table
, NULL
, TABLE_STRING
, dot
+ 1);
1291 return table_log_add_error(r
);
1295 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1297 return table_log_print_error(r
);
1302 static int list_boots(sd_journal
*j
) {
1303 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1304 _cleanup_free_ BootId
*boots
= NULL
;
1310 r
= journal_get_boots(j
, &boots
, &n_boots
);
1312 return log_error_errno(r
, "Failed to determine boots: %m");
1316 table
= table_new("idx", "boot id", "first entry", "last entry");
1321 table_set_width(table
, 0);
1323 r
= table_set_json_field_name(table
, 0, "index");
1325 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1327 (void) table_set_sort(table
, (size_t) 0);
1328 (void) table_set_reverse(table
, 0, arg_reverse
);
1330 FOREACH_ARRAY(i
, boots
, n_boots
) {
1331 r
= table_add_many(table
,
1332 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1333 TABLE_SET_ALIGN_PERCENT
, 100,
1335 TABLE_TIMESTAMP
, i
->first_usec
,
1336 TABLE_TIMESTAMP
, i
->last_usec
);
1338 return table_log_add_error(r
);
1341 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1343 return table_log_print_error(r
);
1348 static int add_boot(sd_journal
*j
) {
1356 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1357 * We can do this only when we logs are coming from the current machine,
1358 * so take the slow path if log location is specified. */
1359 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1360 !arg_directory
&& !arg_file
&& !arg_root
)
1361 return add_match_this_boot(j
, arg_machine
);
1363 if (sd_id128_is_null(arg_boot_id
)) {
1364 r
= journal_find_boot_by_offset(j
, arg_boot_offset
, &arg_boot_id
);
1366 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1369 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1370 "No journal boot entry found from the specified boot offset (%+i).",
1373 r
= journal_find_boot_by_id(j
, arg_boot_id
);
1375 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1376 SD_ID128_TO_STRING(arg_boot_id
));
1378 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1379 "No journal boot entry found from the specified boot ID (%s).",
1380 SD_ID128_TO_STRING(arg_boot_id
));
1383 r
= add_match_boot_id(j
, arg_boot_id
);
1385 return log_error_errno(r
, "Failed to add match: %m");
1387 r
= sd_journal_add_conjunction(j
);
1389 return log_error_errno(r
, "Failed to add conjunction: %m");
1394 static int add_dmesg(sd_journal
*j
) {
1401 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1402 STRLEN("_TRANSPORT=kernel"));
1404 return log_error_errno(r
, "Failed to add match: %m");
1406 r
= sd_journal_add_conjunction(j
);
1408 return log_error_errno(r
, "Failed to add conjunction: %m");
1413 static int get_possible_units(
1419 _cleanup_set_free_free_ Set
*found
= NULL
;
1422 found
= set_new(&string_hash_ops
);
1426 NULSTR_FOREACH(field
, fields
) {
1430 r
= sd_journal_query_unique(j
, field
);
1434 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1437 _cleanup_free_
char *u
= NULL
;
1439 eq
= memchr(data
, '=', size
);
1441 prefix
= eq
- (char*) data
+ 1;
1445 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1449 STRV_FOREACH(pattern
, patterns
)
1450 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1451 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1453 r
= set_consume(found
, u
);
1455 if (r
< 0 && r
!= -EEXIST
)
1463 *units
= TAKE_PTR(found
);
1468 /* This list is supposed to return the superset of unit names
1469 * possibly matched by rules added with add_matches_for_unit... */
1470 #define SYSTEM_UNITS \
1474 "OBJECT_SYSTEMD_UNIT\0" \
1477 /* ... and add_matches_for_user_unit */
1478 #define USER_UNITS \
1479 "_SYSTEMD_USER_UNIT\0" \
1481 "COREDUMP_USER_UNIT\0" \
1482 "OBJECT_SYSTEMD_USER_UNIT\0" \
1483 "_SYSTEMD_USER_SLICE\0"
1485 static int add_units(sd_journal
*j
) {
1486 _cleanup_strv_free_
char **patterns
= NULL
;
1491 STRV_FOREACH(i
, arg_system_units
) {
1492 _cleanup_free_
char *u
= NULL
;
1494 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1498 if (string_is_glob(u
)) {
1499 r
= strv_push(&patterns
, u
);
1504 r
= add_matches_for_unit(j
, u
);
1507 r
= sd_journal_add_disjunction(j
);
1514 if (!strv_isempty(patterns
)) {
1515 _cleanup_set_free_free_ Set
*units
= NULL
;
1518 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1522 SET_FOREACH(u
, units
) {
1523 r
= add_matches_for_unit(j
, u
);
1526 r
= sd_journal_add_disjunction(j
);
1533 patterns
= strv_free(patterns
);
1535 STRV_FOREACH(i
, arg_user_units
) {
1536 _cleanup_free_
char *u
= NULL
;
1538 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1542 if (string_is_glob(u
)) {
1543 r
= strv_push(&patterns
, u
);
1548 r
= add_matches_for_user_unit(j
, u
, getuid());
1551 r
= sd_journal_add_disjunction(j
);
1558 if (!strv_isempty(patterns
)) {
1559 _cleanup_set_free_free_ Set
*units
= NULL
;
1562 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1566 SET_FOREACH(u
, units
) {
1567 r
= add_matches_for_user_unit(j
, u
, getuid());
1570 r
= sd_journal_add_disjunction(j
);
1577 /* Complain if the user request matches but nothing whatsoever was
1578 * found, since otherwise everything would be matched. */
1579 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1582 r
= sd_journal_add_conjunction(j
);
1589 static int add_priorities(sd_journal
*j
) {
1590 char match
[] = "PRIORITY=0";
1594 if (arg_priorities
== 0xFF)
1597 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1598 if (arg_priorities
& (1 << i
)) {
1599 match
[sizeof(match
)-2] = '0' + i
;
1601 r
= sd_journal_add_match(j
, match
, strlen(match
));
1603 return log_error_errno(r
, "Failed to add match: %m");
1606 r
= sd_journal_add_conjunction(j
);
1608 return log_error_errno(r
, "Failed to add conjunction: %m");
1613 static int add_facilities(sd_journal
*j
) {
1617 SET_FOREACH(p
, arg_facilities
) {
1618 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1620 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1622 r
= sd_journal_add_match(j
, match
, strlen(match
));
1624 return log_error_errno(r
, "Failed to add match: %m");
1630 static int add_syslog_identifier(sd_journal
*j
) {
1635 STRV_FOREACH(i
, arg_syslog_identifier
) {
1636 _cleanup_free_
char *u
= NULL
;
1638 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1641 r
= sd_journal_add_match(j
, u
, 0);
1644 r
= sd_journal_add_disjunction(j
);
1649 r
= sd_journal_add_conjunction(j
);
1656 static int add_exclude_identifier(sd_journal
*j
) {
1657 _cleanup_set_free_ Set
*excludes
= NULL
;
1662 r
= set_put_strdupv(&excludes
, arg_exclude_identifier
);
1666 return set_free_and_replace(j
->exclude_syslog_identifiers
, excludes
);
1670 static int format_journal_url(
1680 _cleanup_(memstream_done
) MemStream m
= {};
1684 assert(seed_size
> 0);
1686 f
= memstream_init(&m
);
1693 for (size_t i
= 0; i
< seed_size
; i
++) {
1694 if (i
> 0 && i
% 3 == 0)
1696 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1699 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1702 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1704 fprintf(f
, ";hostname=%s", hn
);
1707 return memstream_finalize(&m
, ret_url
, NULL
);
1711 static int setup_keys(void) {
1713 size_t mpk_size
, seed_size
, state_size
;
1714 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1715 _cleanup_free_
char *p
= NULL
;
1716 uint8_t *mpk
, *seed
, *state
;
1717 _cleanup_close_
int fd
= -EBADF
;
1718 sd_id128_t machine
, boot
;
1723 r
= stat("/var/log/journal", &st
);
1724 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1725 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1727 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1728 log_error("%s is not a directory, must be using persistent logging for FSS.",
1729 "/var/log/journal");
1730 return r
< 0 ? -errno
: -ENOTDIR
;
1733 r
= sd_id128_get_machine(&machine
);
1735 return log_error_errno(r
, "Failed to get machine ID: %m");
1737 r
= sd_id128_get_boot(&boot
);
1739 return log_error_errno(r
, "Failed to get boot ID: %m");
1741 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1742 SD_ID128_FORMAT_VAL(machine
)) < 0)
1747 if (r
< 0 && errno
!= ENOENT
)
1748 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1749 } else if (access(p
, F_OK
) >= 0)
1750 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1751 "Sealing key file %s exists already. Use --force to recreate.", p
);
1753 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1754 SD_ID128_FORMAT_VAL(machine
)) < 0)
1757 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1758 mpk
= alloca_safe(mpk_size
);
1760 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1761 seed
= alloca_safe(seed_size
);
1763 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1764 state
= alloca_safe(state_size
);
1766 log_info("Generating seed...");
1767 r
= crypto_random_bytes(seed
, seed_size
);
1769 return log_error_errno(r
, "Failed to acquire random seed: %m");
1771 log_info("Generating key pair...");
1772 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1774 log_info("Generating sealing key...");
1775 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1777 assert(arg_interval
> 0);
1779 n
= now(CLOCK_REALTIME
);
1783 fd
= mkostemp_safe(k
);
1785 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1787 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1789 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1790 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1792 struct FSSHeader h
= {
1793 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1794 .machine_id
= machine
,
1796 .header_size
= htole64(sizeof(h
)),
1797 .start_usec
= htole64(n
* arg_interval
),
1798 .interval_usec
= htole64(arg_interval
),
1799 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1800 .fsprg_state_size
= htole64(state_size
),
1803 r
= loop_write(fd
, &h
, sizeof(h
));
1805 return log_error_errno(r
, "Failed to write header: %m");
1807 r
= loop_write(fd
, state
, state_size
);
1809 return log_error_errno(r
, "Failed to write state: %m");
1811 if (rename(k
, p
) < 0)
1812 return log_error_errno(errno
, "Failed to link file: %m");
1816 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1818 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1823 hn
= gethostname_malloc();
1825 hostname_cleanup(hn
);
1828 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1830 "The %ssecret sealing key%s has been written to the following local file.\n"
1831 "This key file is automatically updated when the sealing key is advanced.\n"
1832 "It should not be used on multiple hosts.\n"
1836 "The sealing key is automatically changed every %s.\n"
1838 "Please write down the following %ssecret verification key%s. It should be stored\n"
1839 "in a safe location and should not be saved locally on disk.\n"
1841 strempty(hn
), hn
? "/" : "",
1842 SD_ID128_FORMAT_VAL(machine
),
1843 ansi_highlight(), ansi_normal(),
1845 FORMAT_TIMESPAN(arg_interval
, 0),
1846 ansi_highlight(), ansi_normal(),
1847 ansi_highlight_red());
1854 fprintf(stderr
, "%s", ansi_normal());
1856 _cleanup_free_
char *url
= NULL
;
1857 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1861 (void) print_qrcode(stderr
,
1862 "To transfer the verification key to your phone scan the QR code below",
1869 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1870 "Forward-secure sealing not available.");
1874 static int verify(sd_journal
*j
, bool verbose
) {
1880 log_show_color(true);
1882 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1884 usec_t first
= 0, validated
= 0, last
= 0;
1887 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1888 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1891 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1893 /* If the key was invalid give up right-away. */
1896 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1898 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1899 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1901 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1902 if (validated
> 0) {
1903 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1904 "=> Validated from %s to %s, final %s entries not sealed.",
1905 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1906 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1907 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
1908 } else if (last
> 0)
1909 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1910 "=> No sealing yet, %s of entries not sealed.",
1911 FORMAT_TIMESPAN(last
- first
, 0));
1913 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1914 "=> No sealing yet, no entries in file.");
1922 static int varlink_connect_journal(Varlink
**ret_link
) {
1923 const char *address
;
1926 address
= arg_namespace
?
1927 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
1928 "/run/systemd/journal/io.systemd.journal";
1930 r
= varlink_connect_address(ret_link
, address
);
1934 (void) varlink_set_description(*ret_link
, "journal");
1935 (void) varlink_set_relative_timeout(*ret_link
, USEC_INFINITY
);
1940 static int flush_to_var(void) {
1941 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
1944 if (arg_machine
|| arg_namespace
)
1945 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1946 "--flush is not supported in conjunction with %s.",
1947 arg_machine
? "--machine=" : "--namespace=");
1949 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1950 return 0; /* Already flushed, no need to contact journald */
1951 if (errno
!= ENOENT
)
1952 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
1954 r
= varlink_connect_journal(&link
);
1956 return log_error_errno(r
, "Failed to connect to Varlink socket: %m");
1958 return varlink_call_and_log(link
, "io.systemd.Journal.FlushToVar", /* parameters= */ NULL
, /* ret_parameters= */ NULL
);
1961 static int relinquish_var(void) {
1962 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
1965 if (arg_machine
|| arg_namespace
)
1966 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1967 "--(smart-)relinquish-var is not supported in conjunction with %s.",
1968 arg_machine
? "--machine=" : "--namespace=");
1970 r
= varlink_connect_journal(&link
);
1972 return log_error_errno(r
, "Failed to connect to Varlink socket: %m");
1974 return varlink_call_and_log(link
, "io.systemd.Journal.RelinquishVar", /* parameters= */ NULL
, /* ret_parameters= */ NULL
);
1977 static int rotate(void) {
1978 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
1982 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1983 "--rotate is not supported in conjunction with --machine=.");
1985 r
= varlink_connect_journal(&link
);
1987 return log_error_errno(r
, "Failed to connect to Varlink socket: %m");
1989 return varlink_call_and_log(link
, "io.systemd.Journal.Rotate", /* parameters= */ NULL
, /* ret_parameters= */ NULL
);
1992 static int sync_journal(void) {
1993 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
1997 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1998 "--sync is not supported in conjunction with --machine=.");
2000 r
= varlink_connect_journal(&link
);
2001 if (ERRNO_IS_NEG_DISCONNECT(r
) && arg_namespace
)
2002 /* If the namespaced sd-journald instance was shut down due to inactivity, it should already
2003 * be synchronized */
2006 return log_error_errno(r
, "Failed to connect to Varlink socket: %m");
2008 return varlink_call_and_log(link
, "io.systemd.Journal.Synchronize", /* parameters= */ NULL
, /* ret_parameters= */ NULL
);
2011 static int action_list_fields(sd_journal
*j
) {
2018 r
= sd_journal_set_data_threshold(j
, 0);
2020 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2022 r
= sd_journal_query_unique(j
, arg_field
);
2024 return log_error_errno(r
, "Failed to query unique data objects: %m");
2026 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2029 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2032 eq
= memchr(data
, '=', size
);
2034 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2036 printf("%.*s\n", (int) size
, (const char*) data
);
2044 static int update_cursor(sd_journal
*j
) {
2045 _cleanup_free_
char *cursor
= NULL
;
2050 if (!arg_show_cursor
&& !arg_cursor_file
)
2053 r
= sd_journal_get_cursor(j
, &cursor
);
2054 if (r
== -EADDRNOTAVAIL
)
2057 return log_error_errno(r
, "Failed to get cursor: %m");
2059 if (arg_show_cursor
)
2060 printf("-- cursor: %s\n", cursor
);
2062 if (arg_cursor_file
) {
2063 r
= write_string_file(arg_cursor_file
, cursor
, WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_ATOMIC
);
2065 return log_error_errno(r
, "Failed to write new cursor to %s: %m", arg_cursor_file
);
2071 typedef struct Context
{
2072 sd_journal
*journal
;
2076 bool previous_boot_id_valid
;
2077 sd_id128_t previous_boot_id
;
2078 sd_id128_t previous_boot_id_output
;
2079 dual_timestamp previous_ts_output
;
2082 static int show(Context
*c
) {
2088 j
= ASSERT_PTR(c
->journal
);
2090 while (arg_lines
< 0 || n_shown
< arg_lines
|| arg_follow
) {
2092 size_t highlight
[2] = {};
2095 r
= sd_journal_step_one(j
, !arg_reverse
);
2097 return log_error_errno(r
, "Failed to iterate through journal: %m");
2102 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2103 /* If --lines= is set, we usually rely on the n_shown to tell us
2104 * when to stop. However, if --since= is set too, we may end up
2105 * having less than --lines= to output. In this case let's also
2106 * check if the entry is in range. */
2110 r
= sd_journal_get_realtime_usec(j
, &usec
);
2112 return log_error_errno(r
, "Failed to determine timestamp: %m");
2113 if (usec
> arg_until
)
2117 if (arg_since_set
&& (arg_reverse
|| !c
->since_seeked
)) {
2120 r
= sd_journal_get_realtime_usec(j
, &usec
);
2122 return log_error_errno(r
, "Failed to determine timestamp: %m");
2124 if (usec
< arg_since
) {
2126 break; /* Reached the earliest entry */
2128 /* arg_lines >= 0 (!since_seeked):
2129 * We jumped arg_lines back and it seems to be too much */
2130 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2132 return log_error_errno(r
, "Failed to seek to date: %m");
2133 c
->since_seeked
= true;
2135 c
->need_seek
= true;
2138 c
->since_seeked
= true; /* We're surely within the range of --since now */
2141 if (!arg_merge
&& !arg_quiet
) {
2144 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2146 if (c
->previous_boot_id_valid
&&
2147 !sd_id128_equal(boot_id
, c
->previous_boot_id
))
2148 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2149 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2151 c
->previous_boot_id
= boot_id
;
2152 c
->previous_boot_id_valid
= true;
2156 if (arg_compiled_pattern
) {
2157 const void *message
;
2160 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2163 c
->need_seek
= true;
2167 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2170 assert_se(message
= startswith(message
, "MESSAGE="));
2172 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2173 len
- strlen("MESSAGE="), highlight
);
2177 c
->need_seek
= true;
2183 arg_all
* OUTPUT_SHOW_ALL
|
2184 arg_full
* OUTPUT_FULL_WIDTH
|
2185 colors_enabled() * OUTPUT_COLOR
|
2186 arg_catalog
* OUTPUT_CATALOG
|
2187 arg_utc
* OUTPUT_UTC
|
2188 arg_truncate_newline
* OUTPUT_TRUNCATE_NEWLINE
|
2189 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2191 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2192 arg_output_fields
, highlight
, &c
->ellipsized
,
2193 &c
->previous_ts_output
, &c
->previous_boot_id_output
);
2194 c
->need_seek
= true;
2195 if (r
== -EADDRNOTAVAIL
)
2202 /* If journalctl take a long time to process messages, and during that time journal file
2203 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2204 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2205 * in the "following" case. By periodically calling sd_journal_process() during the processing
2206 * loop we shrink the window of time a client instance has open file descriptors for rotated
2207 * (deleted) journal files. */
2208 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2209 r
= sd_journal_process(j
);
2211 return log_error_errno(r
, "Failed to process inotify events: %m");
2218 static int show_and_fflush(Context
*c
, sd_event_source
*s
) {
2226 return sd_event_exit(sd_event_source_get_event(s
), r
);
2232 static int on_journal_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
2233 Context
*c
= ASSERT_PTR(userdata
);
2238 r
= sd_journal_process(c
->journal
);
2240 log_error_errno(r
, "Failed to process journal events: %m");
2241 return sd_event_exit(sd_event_source_get_event(s
), r
);
2244 return show_and_fflush(c
, s
);
2247 static int on_first_event(sd_event_source
*s
, void *userdata
) {
2248 return show_and_fflush(userdata
, s
);
2251 static int on_signal(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
2254 assert(IN_SET(si
->ssi_signo
, SIGTERM
, SIGINT
));
2256 return sd_event_exit(sd_event_source_get_event(s
), si
->ssi_signo
);
2259 static int setup_event(Context
*c
, int fd
, sd_event
**ret
) {
2260 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2268 r
= sd_event_default(&e
);
2270 return log_error_errno(r
, "Failed to allocate sd_event object: %m");
2272 (void) sd_event_add_signal(e
, NULL
, SIGTERM
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2273 (void) sd_event_add_signal(e
, NULL
, SIGINT
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2275 r
= sd_event_add_io(e
, NULL
, fd
, EPOLLIN
, &on_journal_event
, c
);
2277 return log_error_errno(r
, "Failed to add io event source for journal: %m");
2279 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2280 r
= sd_event_add_io(e
, NULL
, STDOUT_FILENO
, EPOLLHUP
|EPOLLERR
, NULL
, INT_TO_PTR(-ECANCELED
));
2282 /* Installing an epoll watch on a regular file doesn't work and fails with EPERM. Which is
2283 * totally OK, handle it gracefully. epoll_ctl() documents EPERM as the error returned when
2284 * the specified fd doesn't support epoll, hence it's safe to check for that. */
2285 log_debug_errno(r
, "Unable to install EPOLLHUP watch on stderr, not watching for hangups.");
2287 return log_error_errno(r
, "Failed to add io event source for stdout: %m");
2289 if (arg_lines
!= 0 || arg_since_set
) {
2290 r
= sd_event_add_defer(e
, NULL
, on_first_event
, c
);
2292 return log_error_errno(r
, "Failed to add defer event source: %m");
2299 static int run(int argc
, char *argv
[]) {
2300 bool need_seek
= false, since_seeked
= false, after_cursor
= false;
2301 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2302 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2303 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2304 _cleanup_free_
char *cursor_from_file
= NULL
;
2305 const char *cursor
= NULL
;
2306 int n_shown
, r
, poll_fd
= -EBADF
;
2308 setlocale(LC_ALL
, "");
2311 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2312 * split up into many files. */
2313 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2315 r
= parse_argv(argc
, argv
);
2322 r
= mount_image_privately_interactively(
2325 DISSECT_IMAGE_GENERIC_ROOT
|
2326 DISSECT_IMAGE_REQUIRE_ROOT
|
2327 DISSECT_IMAGE_VALIDATE_OS
|
2328 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2329 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2331 /* ret_dir_fd= */ NULL
,
2336 arg_root
= strdup(mounted_dir
);
2341 signal(SIGWINCH
, columns_lines_cache_reset
);
2344 switch (arg_action
) {
2346 case ACTION_NEW_ID128
:
2347 return id128_print_new(ID128_PRINT_PRETTY
);
2349 case ACTION_SETUP_KEYS
:
2350 return setup_keys();
2352 case ACTION_LIST_CATALOG
:
2353 case ACTION_DUMP_CATALOG
:
2354 case ACTION_UPDATE_CATALOG
: {
2355 _cleanup_free_
char *database
= NULL
;
2357 database
= path_join(arg_root
, secure_getenv("SYSTEMD_CATALOG") ?: CATALOG_DATABASE
);
2361 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2364 e
= secure_getenv("SYSTEMD_CATALOG_SOURCES");
2369 e
? (const char* const*) STRV_MAKE(e
) : catalog_file_dirs
);
2371 return log_error_errno(r
, "Failed to list catalog: %m");
2373 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2375 pager_open(arg_pager_flags
);
2378 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2380 r
= catalog_list(stdout
, database
, oneline
);
2382 return log_error_errno(r
, "Failed to list catalog: %m");
2389 return flush_to_var();
2391 case ACTION_RELINQUISH_VAR
:
2392 return relinquish_var();
2395 return sync_journal();
2400 case ACTION_LIST_NAMESPACES
:
2401 return list_namespaces(arg_root
);
2404 case ACTION_PRINT_HEADER
:
2406 case ACTION_DISK_USAGE
:
2407 case ACTION_LIST_BOOTS
:
2409 case ACTION_ROTATE_AND_VACUUM
:
2410 case ACTION_LIST_FIELDS
:
2411 case ACTION_LIST_FIELD_NAMES
:
2412 /* These ones require access to the journal files, continue below. */
2416 assert_not_reached();
2420 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
| arg_journal_additional_open_flags
);
2422 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| arg_journal_additional_open_flags
| SD_JOURNAL_OS_ROOT
);
2423 else if (arg_file_stdin
)
2424 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, arg_journal_additional_open_flags
);
2426 r
= sd_journal_open_files(&j
, (const char**) arg_file
, arg_journal_additional_open_flags
);
2427 else if (arg_machine
)
2428 r
= journal_open_machine(&j
, arg_machine
, arg_journal_additional_open_flags
);
2430 r
= sd_journal_open_namespace(
2433 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2434 arg_namespace_flags
| arg_journal_type
| arg_journal_additional_open_flags
);
2436 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2438 r
= journal_access_check_and_warn(j
, arg_quiet
,
2439 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2443 switch (arg_action
) {
2445 case ACTION_NEW_ID128
:
2446 case ACTION_SETUP_KEYS
:
2447 case ACTION_LIST_CATALOG
:
2448 case ACTION_DUMP_CATALOG
:
2449 case ACTION_UPDATE_CATALOG
:
2453 assert_not_reached();
2455 case ACTION_PRINT_HEADER
:
2456 journal_print_header(j
);
2460 return verify(j
, !arg_quiet
);
2462 case ACTION_DISK_USAGE
: {
2465 r
= sd_journal_get_usage(j
, &bytes
);
2469 printf("Archived and active journals take up %s in the file system.\n",
2470 FORMAT_BYTES(bytes
));
2475 case ACTION_LIST_BOOTS
:
2476 return list_boots(j
);
2478 case ACTION_ROTATE_AND_VACUUM
:
2486 case ACTION_VACUUM
: {
2490 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2491 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2493 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2502 case ACTION_LIST_FIELD_NAMES
: {
2505 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2506 printf("%s\n", field
);
2512 case ACTION_LIST_FIELDS
:
2516 assert_not_reached();
2519 if (arg_boot_offset
!= 0 &&
2520 sd_journal_has_runtime_files(j
) > 0 &&
2521 sd_journal_has_persistent_files(j
) == 0) {
2522 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2524 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2529 /* add_boot() must be called first!
2530 * It may need to seek the journal to find parent boot IDs. */
2541 return log_error_errno(r
, "Failed to add filter for units: %m");
2543 r
= add_syslog_identifier(j
);
2545 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2547 r
= add_exclude_identifier(j
);
2549 return log_error_errno(r
, "Failed to add exclude filter for syslog identifiers: %m");
2551 r
= add_priorities(j
);
2555 r
= add_facilities(j
);
2559 r
= add_matches(j
, argv
+ optind
);
2563 if (DEBUG_LOGGING
) {
2564 _cleanup_free_
char *filter
= NULL
;
2566 filter
= journal_make_match_string(j
);
2570 log_debug("Journal filter: %s", filter
);
2573 if (arg_action
== ACTION_LIST_FIELDS
)
2574 return action_list_fields(j
);
2576 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2578 poll_fd
= sd_journal_get_fd(j
);
2579 if (poll_fd
== -EMFILE
) {
2580 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2582 } else if (poll_fd
== -EMEDIUMTYPE
)
2583 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2584 else if (poll_fd
< 0)
2585 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2588 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2589 cursor
= arg_cursor
?: arg_after_cursor
;
2591 if (arg_cursor_file
) {
2592 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2593 if (r
< 0 && r
!= -ENOENT
)
2594 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2597 cursor
= cursor_from_file
;
2598 after_cursor
= true;
2601 after_cursor
= arg_after_cursor
;
2605 r
= sd_journal_seek_cursor(j
, cursor
);
2607 return log_error_errno(r
, "Failed to seek to cursor: %m");
2609 r
= sd_journal_step_one(j
, !arg_reverse
);
2611 return log_error_errno(r
, "Failed to iterate through journal: %m");
2613 if (after_cursor
&& r
> 0) {
2614 /* With --after-cursor=/--cursor-file= we want to skip the first entry only if it's
2615 * the entry the cursor is pointing at, otherwise, if some journal filters are used,
2616 * we might skip the first entry of the filter match, which leads to unexpectedly
2617 * missing journal entries. */
2620 k
= sd_journal_test_cursor(j
, cursor
);
2622 return log_error_errno(k
, "Failed to test cursor against current entry: %m");
2624 /* Current entry matches the one our cursor is pointing at, so let's try
2625 * to advance the next entry. */
2626 r
= sd_journal_step_one(j
, !arg_reverse
);
2630 /* We couldn't find the next entry after the cursor. */
2636 } else if (arg_until_set
&& (arg_reverse
|| arg_lines_needs_seek_end())) {
2637 /* If both --until and any of --reverse and --lines=N is specified, things get
2638 * a little tricky. We seek to the place of --until first. If only --reverse or
2639 * --reverse and --lines is specified, we search backwards and let the output
2640 * counter handle --lines for us. If only --lines is used, we just jump backwards
2641 * arg_lines and search afterwards from there. */
2643 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2645 return log_error_errno(r
, "Failed to seek to date: %m");
2648 r
= sd_journal_previous(j
);
2649 else /* arg_lines_needs_seek_end */
2650 r
= sd_journal_previous_skip(j
, arg_lines
);
2652 } else if (arg_reverse
) {
2653 r
= sd_journal_seek_tail(j
);
2655 return log_error_errno(r
, "Failed to seek to tail: %m");
2657 r
= sd_journal_previous(j
);
2659 } else if (arg_lines_needs_seek_end()) {
2660 r
= sd_journal_seek_tail(j
);
2662 return log_error_errno(r
, "Failed to seek to tail: %m");
2664 r
= sd_journal_previous_skip(j
, arg_lines
);
2666 } else if (arg_since_set
) {
2667 /* This is placed after arg_reverse and arg_lines. If --since is used without
2668 * both, we seek to the place of --since and search afterwards from there.
2669 * If used with --reverse or --lines, we seek to the tail first and check if
2670 * the entry is within the range of --since later. */
2672 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2674 return log_error_errno(r
, "Failed to seek to date: %m");
2675 since_seeked
= true;
2677 r
= sd_journal_next(j
);
2680 r
= sd_journal_seek_head(j
);
2682 return log_error_errno(r
, "Failed to seek to head: %m");
2684 r
= sd_journal_next(j
);
2687 return log_error_errno(r
, "Failed to iterate through journal: %m");
2692 pager_open(arg_pager_flags
);
2694 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2696 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2698 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2700 return log_error_errno(r
, "Failed to get cutoff: %m");
2703 printf("-- Journal begins at %s. --\n",
2704 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2706 printf("-- Journal begins at %s, ends at %s. --\n",
2707 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2708 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2714 .need_seek
= need_seek
,
2715 .since_seeked
= since_seeked
,
2719 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2722 assert(poll_fd
>= 0);
2724 r
= setup_event(&c
, poll_fd
, &e
);
2728 r
= sd_event_loop(e
);
2733 r
= update_cursor(j
);
2737 /* re-send the original signal. */
2746 if (n_shown
== 0 && !arg_quiet
)
2747 printf("-- No entries --\n");
2749 r
= update_cursor(j
);
2753 if (arg_compiled_pattern
&& n_shown
== 0)
2754 /* --grep was used, no error was thrown, but the pattern didn't
2755 * match anything. Let's mimic grep's behavior here and return
2756 * a non-zero exit code, so journalctl --grep can be used
2757 * in scripts and such */
2763 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_SIGNAL(run
);