1 /* SPDX-License-Identifier: LGPL-2.1+ */
13 #include <sys/inotify.h>
18 # define PCRE2_CODE_UNIT_WIDTH 8
23 #include "sd-device.h"
24 #include "sd-journal.h"
27 #include "alloc-util.h"
28 #include "bus-error.h"
31 #include "chattr-util.h"
33 #include "device-private.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-qrcode.h"
46 #include "journal-util.h"
47 #include "journal-vacuum.h"
48 #include "journal-verify.h"
49 #include "locale-util.h"
51 #include "logs-show.h"
52 #include "memory-util.h"
54 #include "mountpoint-util.h"
55 #include "nulstr-util.h"
57 #include "parse-util.h"
58 #include "path-util.h"
59 #include "pretty-print.h"
60 #include "rlimit-util.h"
63 #include "string-table.h"
65 #include "syslog-util.h"
66 #include "terminal-util.h"
67 #include "tmpfile-util.h"
68 #include "unit-name.h"
69 #include "user-util.h"
72 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
73 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
76 /* Special values for arg_lines */
77 ARG_LINES_DEFAULT
= -2,
81 static OutputMode arg_output
= OUTPUT_SHORT
;
82 static bool arg_utc
= false;
83 static bool arg_follow
= false;
84 static bool arg_full
= true;
85 static bool arg_all
= false;
86 static PagerFlags arg_pager_flags
= 0;
87 static int arg_lines
= ARG_LINES_DEFAULT
;
88 static bool arg_no_tail
= false;
89 static bool arg_quiet
= false;
90 static bool arg_merge
= false;
91 static bool arg_boot
= false;
92 static sd_id128_t arg_boot_id
= {};
93 static int arg_boot_offset
= 0;
94 static bool arg_dmesg
= false;
95 static bool arg_no_hostname
= false;
96 static const char *arg_cursor
= NULL
;
97 static const char *arg_cursor_file
= NULL
;
98 static const char *arg_after_cursor
= NULL
;
99 static bool arg_show_cursor
= false;
100 static const char *arg_directory
= NULL
;
101 static char **arg_file
= NULL
;
102 static bool arg_file_stdin
= false;
103 static int arg_priorities
= 0xFF;
104 static char *arg_verify_key
= NULL
;
106 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
107 static bool arg_force
= false;
109 static usec_t arg_since
, arg_until
;
110 static bool arg_since_set
= false, arg_until_set
= false;
111 static char **arg_syslog_identifier
= NULL
;
112 static char **arg_system_units
= NULL
;
113 static char **arg_user_units
= NULL
;
114 static const char *arg_field
= NULL
;
115 static bool arg_catalog
= false;
116 static bool arg_reverse
= false;
117 static int arg_journal_type
= 0;
118 static char *arg_root
= NULL
;
119 static const char *arg_machine
= NULL
;
120 static uint64_t arg_vacuum_size
= 0;
121 static uint64_t arg_vacuum_n_files
= 0;
122 static usec_t arg_vacuum_time
= 0;
123 static char **arg_output_fields
= NULL
;
125 static const char *arg_pattern
= NULL
;
126 static pcre2_code
*arg_compiled_pattern
= NULL
;
127 static int arg_case_sensitive
= -1; /* -1 means be smart */
139 ACTION_UPDATE_CATALOG
,
142 ACTION_RELINQUISH_VAR
,
146 ACTION_ROTATE_AND_VACUUM
,
148 ACTION_LIST_FIELD_NAMES
,
149 } arg_action
= ACTION_SHOW
;
151 typedef struct BootId
{
155 LIST_FIELDS(struct BootId
, boot_list
);
159 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data
*, pcre2_match_data_free
);
160 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code
*, pcre2_code_free
);
162 static int pattern_compile(const char *pattern
, unsigned flags
, pcre2_code
**out
) {
164 PCRE2_SIZE erroroffset
;
167 p
= pcre2_compile((PCRE2_SPTR8
) pattern
,
168 PCRE2_ZERO_TERMINATED
, flags
, &errorcode
, &erroroffset
, NULL
);
170 unsigned char buf
[LINE_MAX
];
172 r
= pcre2_get_error_message(errorcode
, buf
, sizeof buf
);
174 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
175 "Bad pattern \"%s\": %s", pattern
,
176 r
< 0 ? "unknown error" : (char *)buf
);
185 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
186 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
194 if (!path_startswith(devpath
, "/dev/")) {
195 log_error("Devpath does not start with /dev/");
199 if (stat(devpath
, &st
) < 0)
200 return log_error_errno(errno
, "Couldn't stat file: %m");
202 r
= device_new_from_stat_rdev(&device
, &st
);
204 return log_error_errno(r
, "Failed to get device from devnum %u:%u: %m", major(st
.st_rdev
), minor(st
.st_rdev
));
206 for (d
= device
; d
; ) {
207 _cleanup_free_
char *match
= NULL
;
208 const char *subsys
, *sysname
, *devnode
;
211 r
= sd_device_get_subsystem(d
, &subsys
);
215 r
= sd_device_get_sysname(d
, &sysname
);
219 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
223 r
= sd_journal_add_match(j
, match
, 0);
225 return log_error_errno(r
, "Failed to add match: %m");
227 if (sd_device_get_devname(d
, &devnode
) >= 0) {
228 _cleanup_free_
char *match1
= NULL
;
230 r
= stat(devnode
, &st
);
232 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
234 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st
.st_mode
) ? 'b' : 'c', major(st
.st_rdev
), minor(st
.st_rdev
));
238 r
= sd_journal_add_match(j
, match1
, 0);
240 return log_error_errno(r
, "Failed to add match: %m");
244 if (sd_device_get_parent(d
, &parent
) < 0)
250 r
= add_match_this_boot(j
, arg_machine
);
252 return log_error_errno(r
, "Failed to add match for the current boot: %m");
257 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
260 return format_timestamp_utc(buf
, l
, t
);
262 return format_timestamp(buf
, l
, t
);
265 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
266 sd_id128_t id
= SD_ID128_NULL
;
269 if (streq(x
, "all")) {
270 *boot_id
= SD_ID128_NULL
;
273 } else if (strlen(x
) >= 32) {
277 r
= sd_id128_from_string(t
, &id
);
281 if (!IN_SET(*x
, 0, '-', '+'))
285 r
= safe_atoi(x
, &off
);
290 r
= safe_atoi(x
, &off
);
304 static int help(void) {
305 _cleanup_free_
char *link
= NULL
;
308 (void) pager_open(arg_pager_flags
);
310 r
= terminal_urlify_man("journalctl", "1", &link
);
314 printf("%s [OPTIONS...] [MATCHES...]\n\n"
315 "%sQuery the journal.%s\n\n"
317 " --system Show the system journal\n"
318 " --user Show the user journal for the current user\n"
319 " -M --machine=CONTAINER Operate on local container\n"
320 " -S --since=DATE Show entries not older than the specified date\n"
321 " -U --until=DATE Show entries not newer than the specified date\n"
322 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
323 " --after-cursor=CURSOR Show entries after the specified cursor\n"
324 " --show-cursor Print the cursor after all the entries\n"
325 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
326 " -b --boot[=ID] Show current boot or the specified boot\n"
327 " --list-boots Show terse information about recorded boots\n"
328 " -k --dmesg Show kernel message log from the current boot\n"
329 " -u --unit=UNIT Show logs from the specified unit\n"
330 " --user-unit=UNIT Show logs from the specified user unit\n"
331 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
332 " -p --priority=RANGE Show entries with the specified priority\n"
333 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
334 " --case-sensitive[=BOOL] Force case sensitive or insenstive matching\n"
335 " -e --pager-end Immediately jump to the end in the pager\n"
336 " -f --follow Follow the journal\n"
337 " -n --lines[=INTEGER] Number of journal entries to show\n"
338 " --no-tail Show all lines, even in follow mode\n"
339 " -r --reverse Show the newest entries first\n"
340 " -o --output=STRING Change journal output mode (short, short-precise,\n"
341 " short-iso, short-iso-precise, short-full,\n"
342 " short-monotonic, short-unix, verbose, export,\n"
343 " json, json-pretty, json-sse, json-seq, cat,\n"
345 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
346 " --utc Express time in Coordinated Universal Time (UTC)\n"
347 " -x --catalog Add message explanations where available\n"
348 " --no-full Ellipsize fields\n"
349 " -a --all Show all fields, including long and unprintable\n"
350 " -q --quiet Do not show info messages and privilege warning\n"
351 " --no-pager Do not pipe output into a pager\n"
352 " --no-hostname Suppress output of hostname field\n"
353 " -m --merge Show entries from all available journals\n"
354 " -D --directory=PATH Show journal files from directory\n"
355 " --file=PATH Show journal file\n"
356 " --root=ROOT Operate on files below a root directory\n"
357 " --interval=TIME Time interval for changing the FSS sealing key\n"
358 " --verify-key=KEY Specify FSS verification key\n"
359 " --force Override of the FSS key pair with --setup-keys\n"
361 " -h --help Show this help text\n"
362 " --version Show package version\n"
363 " -N --fields List all field names currently used\n"
364 " -F --field=FIELD List all values that a specified field takes\n"
365 " --disk-usage Show total disk usage of all journal files\n"
366 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
367 " --vacuum-files=INT Leave only the specified number of journal files\n"
368 " --vacuum-time=TIME Remove journal files older than specified time\n"
369 " --verify Verify journal file consistency\n"
370 " --sync Synchronize unwritten journal messages to disk\n"
371 " --relinquish-var Stop logging to disk, log to temporary file system\n"
372 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
373 " --flush Flush all journal data from /run into /var\n"
374 " --rotate Request immediate rotation of the journal files\n"
375 " --header Show journal header information\n"
376 " --list-catalog Show all message IDs in the catalog\n"
377 " --dump-catalog Show entries in the message catalog\n"
378 " --update-catalog Update the message catalog database\n"
379 " --setup-keys Generate a new FSS key pair\n"
380 "\nSee the %s for details.\n"
381 , program_invocation_short_name
382 , ansi_highlight(), ansi_normal()
389 static int parse_argv(int argc
, char *argv
[]) {
422 ARG_SMART_RELINQUISH_VAR
,
431 static const struct option options
[] = {
432 { "help", no_argument
, NULL
, 'h' },
433 { "version" , no_argument
, NULL
, ARG_VERSION
},
434 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
435 { "pager-end", no_argument
, NULL
, 'e' },
436 { "follow", no_argument
, NULL
, 'f' },
437 { "force", no_argument
, NULL
, ARG_FORCE
},
438 { "output", required_argument
, NULL
, 'o' },
439 { "all", no_argument
, NULL
, 'a' },
440 { "full", no_argument
, NULL
, 'l' },
441 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
442 { "lines", optional_argument
, NULL
, 'n' },
443 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
444 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
445 { "quiet", no_argument
, NULL
, 'q' },
446 { "merge", no_argument
, NULL
, 'm' },
447 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
448 { "boot", optional_argument
, NULL
, 'b' },
449 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
450 { "dmesg", no_argument
, NULL
, 'k' },
451 { "system", no_argument
, NULL
, ARG_SYSTEM
},
452 { "user", no_argument
, NULL
, ARG_USER
},
453 { "directory", required_argument
, NULL
, 'D' },
454 { "file", required_argument
, NULL
, ARG_FILE
},
455 { "root", required_argument
, NULL
, ARG_ROOT
},
456 { "header", no_argument
, NULL
, ARG_HEADER
},
457 { "identifier", required_argument
, NULL
, 't' },
458 { "priority", required_argument
, NULL
, 'p' },
459 { "grep", required_argument
, NULL
, 'g' },
460 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
461 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
462 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
463 { "verify", no_argument
, NULL
, ARG_VERIFY
},
464 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
465 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
466 { "cursor", required_argument
, NULL
, 'c' },
467 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
468 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
469 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
470 { "since", required_argument
, NULL
, 'S' },
471 { "until", required_argument
, NULL
, 'U' },
472 { "unit", required_argument
, NULL
, 'u' },
473 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
474 { "field", required_argument
, NULL
, 'F' },
475 { "fields", no_argument
, NULL
, 'N' },
476 { "catalog", no_argument
, NULL
, 'x' },
477 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
478 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
479 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
480 { "reverse", no_argument
, NULL
, 'r' },
481 { "machine", required_argument
, NULL
, 'M' },
482 { "utc", no_argument
, NULL
, ARG_UTC
},
483 { "flush", no_argument
, NULL
, ARG_FLUSH
},
484 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
485 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
486 { "sync", no_argument
, NULL
, ARG_SYNC
},
487 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
488 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
489 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
490 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
491 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
492 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
501 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
512 arg_pager_flags
|= PAGER_DISABLE
;
516 arg_pager_flags
|= PAGER_JUMP_TO_END
;
518 if (arg_lines
== ARG_LINES_DEFAULT
)
528 if (streq(optarg
, "help")) {
529 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
533 arg_output
= output_mode_from_string(optarg
);
535 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown output format '%s'.", optarg
);
537 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
556 if (streq(optarg
, "all"))
557 arg_lines
= ARG_LINES_ALL
;
559 r
= safe_atoi(optarg
, &arg_lines
);
560 if (r
< 0 || arg_lines
< 0)
561 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
566 /* Hmm, no argument? Maybe the next
567 * word on the command line is
568 * supposed to be the argument? Let's
569 * see if there is one, and is
573 if (streq(argv
[optind
], "all")) {
574 arg_lines
= ARG_LINES_ALL
;
576 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
590 arg_action
= ACTION_NEW_ID128
;
603 arg_boot_id
= SD_ID128_NULL
;
609 arg_boot_id
= SD_ID128_NULL
;
613 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
615 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
619 /* Hmm, no argument? Maybe the next
620 * word on the command line is
621 * supposed to be the argument? Let's
622 * see if there is one and is parsable
623 * as a boot descriptor... */
624 } else if (optind
< argc
) {
625 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
634 arg_action
= ACTION_LIST_BOOTS
;
638 arg_boot
= arg_dmesg
= true;
642 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
646 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
650 arg_machine
= optarg
;
654 arg_directory
= optarg
;
658 if (streq(optarg
, "-"))
659 /* An undocumented feature: we can read journal files from STDIN. We don't document
660 * this though, since after all we only support this for mmap-able, seekable files, and
661 * not for example pipes which are probably the primary usecase for reading things from
662 * STDIN. To avoid confusion we hence don't document this feature. */
663 arg_file_stdin
= true;
665 r
= glob_extend(&arg_file
, optarg
);
667 return log_error_errno(r
, "Failed to add paths: %m");
672 r
= parse_path_argument_and_warn(optarg
, true, &arg_root
);
681 case ARG_CURSOR_FILE
:
682 arg_cursor_file
= optarg
;
685 case ARG_AFTER_CURSOR
:
686 arg_after_cursor
= optarg
;
689 case ARG_SHOW_CURSOR
:
690 arg_show_cursor
= true;
694 arg_action
= ACTION_PRINT_HEADER
;
698 arg_action
= ACTION_VERIFY
;
702 arg_action
= ACTION_DISK_USAGE
;
705 case ARG_VACUUM_SIZE
:
706 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
708 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
710 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
713 case ARG_VACUUM_FILES
:
714 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
716 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
718 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
721 case ARG_VACUUM_TIME
:
722 r
= parse_sec(optarg
, &arg_vacuum_time
);
724 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
726 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
735 arg_action
= ACTION_SETUP_KEYS
;
739 r
= free_and_strdup(&arg_verify_key
, optarg
);
742 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
743 * in ps or htop output. */
744 memset(optarg
, 'x', strlen(optarg
));
746 arg_action
= ACTION_VERIFY
;
751 r
= parse_sec(optarg
, &arg_interval
);
752 if (r
< 0 || arg_interval
<= 0)
753 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
754 "Failed to parse sealing key change interval: %s", optarg
);
761 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
762 "Compiled without forward-secure sealing support.");
768 dots
= strstr(optarg
, "..");
770 _cleanup_free_
char *a
= NULL
;
774 a
= strndup(optarg
, dots
- optarg
);
778 from
= log_level_from_string(a
);
779 to
= log_level_from_string(dots
+ 2);
781 if (from
< 0 || to
< 0)
782 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
783 "Failed to parse log level range %s", optarg
);
788 for (i
= from
; i
<= to
; i
++)
789 arg_priorities
|= 1 << i
;
791 for (i
= to
; i
<= from
; i
++)
792 arg_priorities
|= 1 << i
;
798 p
= log_level_from_string(optarg
);
800 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
801 "Unknown log level %s", optarg
);
805 for (i
= 0; i
<= p
; i
++)
806 arg_priorities
|= 1 << i
;
814 arg_pattern
= optarg
;
817 case ARG_CASE_SENSITIVE
:
819 r
= parse_boolean(optarg
);
821 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
822 arg_case_sensitive
= r
;
824 arg_case_sensitive
= true;
829 case ARG_CASE_SENSITIVE
:
830 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Compiled without pattern matching support");
834 r
= parse_timestamp(optarg
, &arg_since
);
836 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
837 "Failed to parse timestamp: %s", optarg
);
838 arg_since_set
= true;
842 r
= parse_timestamp(optarg
, &arg_until
);
844 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
845 "Failed to parse timestamp: %s", optarg
);
846 arg_until_set
= true;
850 r
= strv_extend(&arg_syslog_identifier
, optarg
);
856 r
= strv_extend(&arg_system_units
, optarg
);
862 r
= strv_extend(&arg_user_units
, optarg
);
868 arg_action
= ACTION_LIST_FIELDS
;
873 arg_action
= ACTION_LIST_FIELD_NAMES
;
876 case ARG_NO_HOSTNAME
:
877 arg_no_hostname
= true;
884 case ARG_LIST_CATALOG
:
885 arg_action
= ACTION_LIST_CATALOG
;
888 case ARG_DUMP_CATALOG
:
889 arg_action
= ACTION_DUMP_CATALOG
;
892 case ARG_UPDATE_CATALOG
:
893 arg_action
= ACTION_UPDATE_CATALOG
;
905 arg_action
= ACTION_FLUSH
;
908 case ARG_SMART_RELINQUISH_VAR
: {
909 int root_mnt_id
, log_mnt_id
;
911 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
912 * if it's on the same mount as the root file system there's no point in
913 * relinquishing access and we can leave journald write to it until the very last
916 r
= path_get_mnt_id("/", &root_mnt_id
);
918 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
920 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
922 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
923 else if (root_mnt_id
== log_mnt_id
) {
924 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
927 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
933 case ARG_RELINQUISH_VAR
:
934 arg_action
= ACTION_RELINQUISH_VAR
;
938 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
942 arg_action
= ACTION_SYNC
;
945 case ARG_OUTPUT_FIELDS
: {
946 _cleanup_strv_free_
char **v
= NULL
;
948 v
= strv_split(optarg
, ",");
952 if (!arg_output_fields
)
953 arg_output_fields
= TAKE_PTR(v
);
955 r
= strv_extend_strv(&arg_output_fields
, v
, true);
966 assert_not_reached("Unhandled option");
969 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
972 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
> 1) {
973 log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root.");
977 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
) {
978 log_error("--since= must be before --until=.");
982 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1) {
983 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
987 if (arg_follow
&& arg_reverse
) {
988 log_error("Please specify either --reverse= or --follow=, not both.");
992 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
) {
993 log_error("Extraneous arguments starting with '%s'", argv
[optind
]);
997 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
) {
998 log_error("Using --boot or --list-boots with --merge is not supported.");
1002 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1003 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1004 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1005 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1006 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1010 arg_system_units
= strv_free(arg_system_units
);
1017 if (arg_case_sensitive
>= 0)
1018 flags
= !arg_case_sensitive
* PCRE2_CASELESS
;
1020 _cleanup_(pcre2_match_data_freep
) pcre2_match_data
*md
= NULL
;
1022 _cleanup_(pcre2_code_freep
) pcre2_code
*cs
= NULL
;
1024 md
= pcre2_match_data_create(1, NULL
);
1028 r
= pattern_compile("[[:upper:]]", 0, &cs
);
1032 r
= pcre2_match(cs
, (PCRE2_SPTR8
) arg_pattern
, PCRE2_ZERO_TERMINATED
, 0, 0, md
, NULL
);
1035 flags
= !has_case
* PCRE2_CASELESS
;
1038 log_debug("Doing case %s matching based on %s",
1039 flags
& PCRE2_CASELESS
? "insensitive" : "sensitive",
1040 arg_case_sensitive
>= 0 ? "request" : "pattern casing");
1042 r
= pattern_compile(arg_pattern
, flags
, &arg_compiled_pattern
);
1051 static int add_matches(sd_journal
*j
, char **args
) {
1053 bool have_term
= false;
1057 STRV_FOREACH(i
, args
) {
1060 if (streq(*i
, "+")) {
1063 r
= sd_journal_add_disjunction(j
);
1066 } else if (path_is_absolute(*i
)) {
1067 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1070 r
= chase_symlinks(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1072 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1074 if (lstat(p
, &st
) < 0)
1075 return log_error_errno(errno
, "Couldn't stat file: %m");
1077 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1078 if (executable_is_script(p
, &interpreter
) > 0) {
1079 _cleanup_free_
char *comm
;
1081 comm
= strndup(basename(p
), 15);
1085 t
= strjoin("_COMM=", comm
);
1089 /* Append _EXE only if the interpreter is not a link.
1090 Otherwise, it might be outdated often. */
1091 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1092 t2
= strjoin("_EXE=", interpreter
);
1097 t
= strjoin("_EXE=", p
);
1102 r
= sd_journal_add_match(j
, t
, 0);
1105 r
= sd_journal_add_match(j
, t2
, 0);
1107 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1108 r
= add_matches_for_device(j
, p
);
1112 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1113 "File is neither a device node, nor regular file, nor executable: %s",
1118 r
= sd_journal_add_match(j
, *i
, 0);
1123 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1126 if (!strv_isempty(args
) && !have_term
)
1127 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1128 "\"+\" can only be used between terms");
1133 static void boot_id_free_all(BootId
*l
) {
1137 LIST_REMOVE(boot_list
, l
, i
);
1142 static int discover_next_boot(sd_journal
*j
,
1143 sd_id128_t previous_boot_id
,
1147 _cleanup_free_ BootId
*next_boot
= NULL
;
1148 char match
[9+32+1] = "_BOOT_ID=";
1155 /* We expect the journal to be on the last position of a boot
1156 * (in relation to the direction we are going), so that the next
1157 * invocation of sd_journal_next/previous will be from a different
1158 * boot. We then collect any information we desire and then jump
1159 * to the last location of the new boot by using a _BOOT_ID match
1160 * coming from the other journal direction. */
1162 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1163 * we can actually advance to a *different* boot. */
1164 sd_journal_flush_matches(j
);
1168 r
= sd_journal_previous(j
);
1170 r
= sd_journal_next(j
);
1174 return 0; /* End of journal, yay. */
1176 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1180 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1181 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1182 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1183 * complete than the main entry array, and hence might reference an entry that's not actually the last
1184 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1185 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1188 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1190 next_boot
= new0(BootId
, 1);
1194 next_boot
->id
= boot_id
;
1196 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1200 /* Now seek to the last occurrence of this boot ID. */
1201 sd_id128_to_string(next_boot
->id
, match
+ 9);
1202 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1207 r
= sd_journal_seek_head(j
);
1209 r
= sd_journal_seek_tail(j
);
1214 r
= sd_journal_next(j
);
1216 r
= sd_journal_previous(j
);
1220 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1221 "Whoopsie! We found a boot ID but can't read its last entry."); /* This shouldn't happen. We just came from this very boot ID. */
1223 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1227 *ret
= TAKE_PTR(next_boot
);
1232 static int get_boots(
1235 sd_id128_t
*boot_id
,
1240 BootId
*head
= NULL
, *tail
= NULL
, *id
;
1241 const bool advance_older
= boot_id
&& offset
<= 0;
1242 sd_id128_t previous_boot_id
;
1246 /* Adjust for the asymmetry that offset 0 is
1247 * the last (and current) boot, while 1 is considered the
1248 * (chronological) first boot in the journal. */
1249 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1251 /* Advance to the earliest/latest occurrence of our reference
1252 * boot ID (taking our lookup direction into account), so that
1253 * discover_next_boot() can do its job.
1254 * If no reference is given, the journal head/tail will do,
1255 * they're "virtual" boots after all. */
1256 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1257 char match
[9+32+1] = "_BOOT_ID=";
1259 sd_journal_flush_matches(j
);
1261 sd_id128_to_string(*boot_id
, match
+ 9);
1262 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1267 r
= sd_journal_seek_head(j
); /* seek to oldest */
1269 r
= sd_journal_seek_tail(j
); /* seek to newest */
1274 r
= sd_journal_next(j
); /* read the oldest entry */
1276 r
= sd_journal_previous(j
); /* read the most recently added entry */
1281 else if (offset
== 0) {
1286 /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot
1287 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1288 * the following entry, which must then have an older/newer boot ID */
1292 r
= sd_journal_seek_tail(j
); /* seek to newest */
1294 r
= sd_journal_seek_head(j
); /* seek to oldest */
1298 /* No sd_journal_next()/_previous() here.
1300 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1301 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1305 previous_boot_id
= SD_ID128_NULL
;
1307 _cleanup_free_ BootId
*current
= NULL
;
1309 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1311 boot_id_free_all(head
);
1318 previous_boot_id
= current
->id
;
1322 offset
+= advance_older
? 1 : -1;
1327 *boot_id
= current
->id
;
1331 LIST_FOREACH(boot_list
, id
, head
) {
1332 if (sd_id128_equal(id
->id
, current
->id
)) {
1333 /* boot id already stored, something wrong with the journal files */
1334 /* exiting as otherwise this problem would cause forever loop */
1338 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1339 tail
= TAKE_PTR(current
);
1348 sd_journal_flush_matches(j
);
1353 static int list_boots(sd_journal
*j
) {
1355 BootId
*id
, *all_ids
;
1359 count
= get_boots(j
, &all_ids
, NULL
, 0);
1361 return log_error_errno(count
, "Failed to determine boots: %m");
1365 (void) pager_open(arg_pager_flags
);
1367 /* numbers are one less, but we need an extra char for the sign */
1368 w
= DECIMAL_STR_WIDTH(count
- 1) + 1;
1371 LIST_FOREACH(boot_list
, id
, all_ids
) {
1372 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1374 printf("% *i " SD_ID128_FORMAT_STR
" %s—%s\n",
1376 SD_ID128_FORMAT_VAL(id
->id
),
1377 format_timestamp_maybe_utc(a
, sizeof(a
), id
->first
),
1378 format_timestamp_maybe_utc(b
, sizeof(b
), id
->last
));
1382 boot_id_free_all(all_ids
);
1387 static int add_boot(sd_journal
*j
) {
1388 char match
[9+32+1] = "_BOOT_ID=";
1397 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1398 * We can do this only when we logs are coming from the current machine,
1399 * so take the slow path if log location is specified. */
1400 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1401 !arg_directory
&& !arg_file
&& !arg_root
)
1403 return add_match_this_boot(j
, arg_machine
);
1405 boot_id
= arg_boot_id
;
1406 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1409 const char *reason
= (r
== 0) ? "No such boot ID in journal" : strerror_safe(r
);
1411 if (sd_id128_is_null(arg_boot_id
))
1412 log_error("Data from the specified boot (%+i) is not available: %s",
1413 arg_boot_offset
, reason
);
1415 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1416 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1418 return r
== 0 ? -ENODATA
: r
;
1421 sd_id128_to_string(boot_id
, match
+ 9);
1423 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1425 return log_error_errno(r
, "Failed to add match: %m");
1427 r
= sd_journal_add_conjunction(j
);
1429 return log_error_errno(r
, "Failed to add conjunction: %m");
1434 static int add_dmesg(sd_journal
*j
) {
1441 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1442 STRLEN("_TRANSPORT=kernel"));
1444 return log_error_errno(r
, "Failed to add match: %m");
1446 r
= sd_journal_add_conjunction(j
);
1448 return log_error_errno(r
, "Failed to add conjunction: %m");
1453 static int get_possible_units(
1459 _cleanup_set_free_free_ Set
*found
;
1463 found
= set_new(&string_hash_ops
);
1467 NULSTR_FOREACH(field
, fields
) {
1471 r
= sd_journal_query_unique(j
, field
);
1475 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1476 char **pattern
, *eq
;
1478 _cleanup_free_
char *u
= NULL
;
1480 eq
= memchr(data
, '=', size
);
1482 prefix
= eq
- (char*) data
+ 1;
1486 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1490 STRV_FOREACH(pattern
, patterns
)
1491 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1492 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1494 r
= set_consume(found
, u
);
1496 if (r
< 0 && r
!= -EEXIST
)
1504 *units
= TAKE_PTR(found
);
1509 /* This list is supposed to return the superset of unit names
1510 * possibly matched by rules added with add_matches_for_unit... */
1511 #define SYSTEM_UNITS \
1515 "OBJECT_SYSTEMD_UNIT\0" \
1518 /* ... and add_matches_for_user_unit */
1519 #define USER_UNITS \
1520 "_SYSTEMD_USER_UNIT\0" \
1522 "COREDUMP_USER_UNIT\0" \
1523 "OBJECT_SYSTEMD_USER_UNIT\0" \
1524 "_SYSTEMD_USER_SLICE\0"
1526 static int add_units(sd_journal
*j
) {
1527 _cleanup_strv_free_
char **patterns
= NULL
;
1533 STRV_FOREACH(i
, arg_system_units
) {
1534 _cleanup_free_
char *u
= NULL
;
1536 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1540 if (string_is_glob(u
)) {
1541 r
= strv_push(&patterns
, u
);
1546 r
= add_matches_for_unit(j
, u
);
1549 r
= sd_journal_add_disjunction(j
);
1556 if (!strv_isempty(patterns
)) {
1557 _cleanup_set_free_free_ Set
*units
= NULL
;
1561 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1565 SET_FOREACH(u
, units
, it
) {
1566 r
= add_matches_for_unit(j
, u
);
1569 r
= sd_journal_add_disjunction(j
);
1576 patterns
= strv_free(patterns
);
1578 STRV_FOREACH(i
, arg_user_units
) {
1579 _cleanup_free_
char *u
= NULL
;
1581 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1585 if (string_is_glob(u
)) {
1586 r
= strv_push(&patterns
, u
);
1591 r
= add_matches_for_user_unit(j
, u
, getuid());
1594 r
= sd_journal_add_disjunction(j
);
1601 if (!strv_isempty(patterns
)) {
1602 _cleanup_set_free_free_ Set
*units
= NULL
;
1606 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1610 SET_FOREACH(u
, units
, it
) {
1611 r
= add_matches_for_user_unit(j
, u
, getuid());
1614 r
= sd_journal_add_disjunction(j
);
1621 /* Complain if the user request matches but nothing whatsoever was
1622 * found, since otherwise everything would be matched. */
1623 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1626 r
= sd_journal_add_conjunction(j
);
1633 static int add_priorities(sd_journal
*j
) {
1634 char match
[] = "PRIORITY=0";
1638 if (arg_priorities
== 0xFF)
1641 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1642 if (arg_priorities
& (1 << i
)) {
1643 match
[sizeof(match
)-2] = '0' + i
;
1645 r
= sd_journal_add_match(j
, match
, strlen(match
));
1647 return log_error_errno(r
, "Failed to add match: %m");
1650 r
= sd_journal_add_conjunction(j
);
1652 return log_error_errno(r
, "Failed to add conjunction: %m");
1657 static int add_syslog_identifier(sd_journal
*j
) {
1663 STRV_FOREACH(i
, arg_syslog_identifier
) {
1664 _cleanup_free_
char *u
= NULL
;
1666 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1669 r
= sd_journal_add_match(j
, u
, 0);
1672 r
= sd_journal_add_disjunction(j
);
1677 r
= sd_journal_add_conjunction(j
);
1684 static int setup_keys(void) {
1686 size_t mpk_size
, seed_size
, state_size
, i
;
1687 uint8_t *mpk
, *seed
, *state
;
1689 sd_id128_t machine
, boot
;
1690 char *p
= NULL
, *k
= NULL
;
1695 r
= stat("/var/log/journal", &st
);
1696 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1697 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1699 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1700 log_error("%s is not a directory, must be using persistent logging for FSS.",
1701 "/var/log/journal");
1702 return r
< 0 ? -errno
: -ENOTDIR
;
1705 r
= sd_id128_get_machine(&machine
);
1707 return log_error_errno(r
, "Failed to get machine ID: %m");
1709 r
= sd_id128_get_boot(&boot
);
1711 return log_error_errno(r
, "Failed to get boot ID: %m");
1713 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1714 SD_ID128_FORMAT_VAL(machine
)) < 0)
1719 if (r
< 0 && errno
!= ENOENT
) {
1720 r
= log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1723 } else if (access(p
, F_OK
) >= 0) {
1724 log_error("Sealing key file %s exists already. Use --force to recreate.", p
);
1729 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1730 SD_ID128_FORMAT_VAL(machine
)) < 0) {
1735 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1736 mpk
= alloca(mpk_size
);
1738 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1739 seed
= alloca(seed_size
);
1741 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1742 state
= alloca(state_size
);
1744 fd
= open("/dev/random", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1746 r
= log_error_errno(errno
, "Failed to open /dev/random: %m");
1750 log_info("Generating seed...");
1751 r
= loop_read_exact(fd
, seed
, seed_size
, true);
1753 log_error_errno(r
, "Failed to read random seed: %m");
1757 log_info("Generating key pair...");
1758 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1760 log_info("Generating sealing key...");
1761 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1763 assert(arg_interval
> 0);
1765 n
= now(CLOCK_REALTIME
);
1769 fd
= mkostemp_safe(k
);
1771 r
= log_error_errno(fd
, "Failed to open %s: %m", k
);
1775 /* Enable secure remove, exclusion from dump, synchronous
1776 * writing and in-place updating */
1777 r
= chattr_fd(fd
, FS_SECRM_FL
|FS_NODUMP_FL
|FS_SYNC_FL
|FS_NOCOW_FL
, FS_SECRM_FL
|FS_NODUMP_FL
|FS_SYNC_FL
|FS_NOCOW_FL
, NULL
);
1779 log_warning_errno(r
, "Failed to set file attributes: %m");
1782 memcpy(h
.signature
, "KSHHRHLP", 8);
1783 h
.machine_id
= machine
;
1785 h
.header_size
= htole64(sizeof(h
));
1786 h
.start_usec
= htole64(n
* arg_interval
);
1787 h
.interval_usec
= htole64(arg_interval
);
1788 h
.fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
);
1789 h
.fsprg_state_size
= htole64(state_size
);
1791 r
= loop_write(fd
, &h
, sizeof(h
), false);
1793 log_error_errno(r
, "Failed to write header: %m");
1797 r
= loop_write(fd
, state
, state_size
, false);
1799 log_error_errno(r
, "Failed to write state: %m");
1803 if (link(k
, p
) < 0) {
1804 r
= log_error_errno(errno
, "Failed to link file: %m");
1811 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1812 "the following local file. This key file is automatically updated when the\n"
1813 "sealing key is advanced. It should not be used on multiple hosts.\n"
1817 "Please write down the following %ssecret verification key%s. It should be stored\n"
1818 "at a safe location and should not be saved locally on disk.\n"
1820 ansi_highlight(), ansi_normal(),
1822 ansi_highlight(), ansi_normal(),
1823 ansi_highlight_red());
1826 for (i
= 0; i
< seed_size
; i
++) {
1827 if (i
> 0 && i
% 3 == 0)
1829 printf("%02x", ((uint8_t*) seed
)[i
]);
1832 printf("/%llx-%llx\n", (unsigned long long) n
, (unsigned long long) arg_interval
);
1835 char tsb
[FORMAT_TIMESPAN_MAX
], *hn
;
1839 "The sealing key is automatically changed every %s.\n",
1841 format_timespan(tsb
, sizeof(tsb
), arg_interval
, 0));
1843 hn
= gethostname_malloc();
1846 hostname_cleanup(hn
);
1847 fprintf(stderr
, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR
".\n", hn
, SD_ID128_FORMAT_VAL(machine
));
1849 fprintf(stderr
, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR
".\n", SD_ID128_FORMAT_VAL(machine
));
1852 /* If this is not an UTF-8 system don't print any QR codes */
1853 if (is_locale_utf8()) {
1854 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr
);
1855 print_qr_code(stderr
, seed
, seed_size
, n
, arg_interval
, hn
, machine
);
1875 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1876 "Forward-secure sealing not available.");
1880 static int verify(sd_journal
*j
) {
1887 log_show_color(true);
1889 ORDERED_HASHMAP_FOREACH(f
, j
->files
, i
) {
1891 usec_t first
= 0, validated
= 0, last
= 0;
1894 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1895 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1898 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, true);
1900 /* If the key was invalid give up right-away. */
1903 log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1906 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
], c
[FORMAT_TIMESPAN_MAX
];
1907 log_info("PASS: %s", f
->path
);
1909 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1910 if (validated
> 0) {
1911 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1912 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1913 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1914 format_timespan(c
, sizeof(c
), last
> validated
? last
- validated
: 0, 0));
1915 } else if (last
> 0)
1916 log_info("=> No sealing yet, %s of entries not sealed.",
1917 format_timespan(c
, sizeof(c
), last
- first
, 0));
1919 log_info("=> No sealing yet, no entries in file.");
1927 static int simple_varlink_call(const char *option
, const char *method
) {
1928 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
1933 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
1935 r
= varlink_connect_address(&link
, "/run/systemd/journal/io.systemd.journal");
1937 return log_error_errno(r
, "Failed to connect to /run/systemd/journal/io.systemd.journal: %m");
1939 (void) varlink_set_description(link
, "journal");
1940 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
1942 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
1944 return log_error_errno(r
, "Failed to execute varlink call: %m");
1946 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
1947 "Failed to execute varlink call: %s", error
);
1952 static int flush_to_var(void) {
1953 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
1956 static int relinquish_var(void) {
1957 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
1960 static int rotate(void) {
1961 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
1964 static int sync_journal(void) {
1965 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
1968 static int wait_for_change(sd_journal
*j
, int poll_fd
) {
1969 struct pollfd pollfds
[] = {
1970 { .fd
= poll_fd
, .events
= POLLIN
},
1971 { .fd
= STDOUT_FILENO
},
1979 assert(poll_fd
>= 0);
1981 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
1982 * i.e. when it is closed. */
1984 r
= sd_journal_get_timeout(j
, &timeout
);
1986 return log_error_errno(r
, "Failed to determine journal waiting time: %m");
1988 if (ppoll(pollfds
, ELEMENTSOF(pollfds
),
1989 timeout
== USEC_INFINITY
? NULL
: timespec_store(&ts
, timeout
), NULL
) < 0) {
1993 return log_error_errno(errno
, "Couldn't wait for journal event: %m");
1996 if (pollfds
[1].revents
& (POLLHUP
|POLLERR
)) /* STDOUT has been closed? */
1997 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
),
1998 "Standard output has been closed.");
2000 r
= sd_journal_process(j
);
2002 return log_error_errno(r
, "Failed to process journal events: %m");
2007 int main(int argc
, char *argv
[]) {
2008 bool previous_boot_id_valid
= false, first_line
= true, ellipsized
= false, need_seek
= false;
2009 bool use_cursor
= false, after_cursor
= false;
2010 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2011 sd_id128_t previous_boot_id
;
2012 int n_shown
= 0, r
, poll_fd
= -1;
2014 setlocale(LC_ALL
, "");
2015 log_show_color(true);
2016 log_parse_environment();
2019 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2020 * split up into many files. */
2021 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2023 r
= parse_argv(argc
, argv
);
2027 signal(SIGWINCH
, columns_lines_cache_reset
);
2030 switch (arg_action
) {
2032 case ACTION_NEW_ID128
:
2033 r
= id128_print_new(ID128_PRINT_PRETTY
);
2036 case ACTION_SETUP_KEYS
:
2040 case ACTION_LIST_CATALOG
:
2041 case ACTION_DUMP_CATALOG
:
2042 case ACTION_UPDATE_CATALOG
: {
2043 _cleanup_free_
char *database
;
2045 database
= path_join(arg_root
, CATALOG_DATABASE
);
2051 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2052 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2054 log_error_errno(r
, "Failed to list catalog: %m");
2056 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2058 (void) pager_open(arg_pager_flags
);
2061 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2063 r
= catalog_list(stdout
, database
, oneline
);
2065 log_error_errno(r
, "Failed to list catalog: %m");
2075 case ACTION_RELINQUISH_VAR
:
2076 r
= relinquish_var();
2088 case ACTION_PRINT_HEADER
:
2090 case ACTION_DISK_USAGE
:
2091 case ACTION_LIST_BOOTS
:
2093 case ACTION_ROTATE_AND_VACUUM
:
2094 case ACTION_LIST_FIELDS
:
2095 case ACTION_LIST_FIELD_NAMES
:
2096 /* These ones require access to the journal files, continue below. */
2100 assert_not_reached("Unknown action");
2104 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2106 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2107 else if (arg_file_stdin
)
2108 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2110 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2111 else if (arg_machine
) {
2112 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2113 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2114 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2117 if (geteuid() != 0) {
2118 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2119 * the container, thus we need root privileges to override them. */
2120 r
= log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2124 r
= sd_bus_open_system(&bus
);
2126 log_error_errno(r
, "Failed to open system bus: %m");
2130 r
= sd_bus_call_method(
2132 "org.freedesktop.machine1",
2133 "/org/freedesktop/machine1",
2134 "org.freedesktop.machine1.Manager",
2135 "OpenMachineRootDirectory",
2140 log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2144 r
= sd_bus_message_read(reply
, "h", &fd
);
2146 bus_log_parse_error(r
);
2150 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2152 r
= log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2156 r
= sd_journal_open_directory_fd(&j
, fd
, SD_JOURNAL_OS_ROOT
);
2160 r
= sd_journal_open(&j
, !arg_merge
*SD_JOURNAL_LOCAL_ONLY
+ arg_journal_type
);
2162 log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2166 r
= journal_access_check_and_warn(j
, arg_quiet
,
2167 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2171 switch (arg_action
) {
2173 case ACTION_NEW_ID128
:
2174 case ACTION_SETUP_KEYS
:
2175 case ACTION_LIST_CATALOG
:
2176 case ACTION_DUMP_CATALOG
:
2177 case ACTION_UPDATE_CATALOG
:
2181 assert_not_reached("Unexpected action.");
2183 case ACTION_PRINT_HEADER
:
2184 journal_print_header(j
);
2192 case ACTION_DISK_USAGE
: {
2194 char sbytes
[FORMAT_BYTES_MAX
];
2196 r
= sd_journal_get_usage(j
, &bytes
);
2200 printf("Archived and active journals take up %s in the file system.\n",
2201 format_bytes(sbytes
, sizeof(sbytes
), bytes
));
2205 case ACTION_LIST_BOOTS
:
2209 case ACTION_ROTATE_AND_VACUUM
:
2217 case ACTION_VACUUM
: {
2221 HASHMAP_FOREACH(d
, j
->directories_by_path
, i
) {
2224 q
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2226 log_error_errno(q
, "Failed to vacuum %s: %m", d
->path
);
2234 case ACTION_LIST_FIELD_NAMES
: {
2237 SD_JOURNAL_FOREACH_FIELD(j
, field
) {
2238 printf("%s\n", field
);
2247 case ACTION_LIST_FIELDS
:
2251 assert_not_reached("Unknown action");
2254 if (arg_boot_offset
!= 0 &&
2255 sd_journal_has_runtime_files(j
) > 0 &&
2256 sd_journal_has_persistent_files(j
) == 0) {
2257 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2261 /* add_boot() must be called first!
2262 * It may need to seek the journal to find parent boot IDs. */
2273 log_error_errno(r
, "Failed to add filter for units: %m");
2277 r
= add_syslog_identifier(j
);
2279 log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2283 r
= add_priorities(j
);
2287 r
= add_matches(j
, argv
+ optind
);
2291 if (DEBUG_LOGGING
) {
2292 _cleanup_free_
char *filter
;
2294 filter
= journal_make_match_string(j
);
2298 log_debug("Journal filter: %s", filter
);
2301 if (arg_action
== ACTION_LIST_FIELDS
) {
2307 r
= sd_journal_set_data_threshold(j
, 0);
2309 log_error_errno(r
, "Failed to unset data size threshold: %m");
2313 r
= sd_journal_query_unique(j
, arg_field
);
2315 log_error_errno(r
, "Failed to query unique data objects: %m");
2319 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2322 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2325 eq
= memchr(data
, '=', size
);
2327 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2329 printf("%.*s\n", (int) size
, (const char*) data
);
2338 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2340 poll_fd
= sd_journal_get_fd(j
);
2341 if (poll_fd
== -EMFILE
) {
2342 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2344 } else if (poll_fd
== -EMEDIUMTYPE
) {
2345 log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2347 } else if (poll_fd
< 0) {
2348 log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2353 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2354 _cleanup_free_
char *cursor_from_file
= NULL
;
2355 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2357 if (arg_cursor_file
) {
2358 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2359 if (r
< 0 && r
!= -ENOENT
) {
2360 log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2365 cursor
= cursor_from_file
;
2366 after_cursor
= true;
2369 after_cursor
= !!arg_after_cursor
;
2372 r
= sd_journal_seek_cursor(j
, cursor
);
2374 log_error_errno(r
, "Failed to seek to cursor: %m");
2383 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2385 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2387 if (after_cursor
&& r
< 2) {
2388 /* We couldn't find the next entry after the cursor. */
2395 } else if (arg_since_set
&& !arg_reverse
) {
2396 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2398 log_error_errno(r
, "Failed to seek to date: %m");
2401 r
= sd_journal_next(j
);
2403 } else if (arg_until_set
&& arg_reverse
) {
2404 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2406 log_error_errno(r
, "Failed to seek to date: %m");
2409 r
= sd_journal_previous(j
);
2411 } else if (arg_reverse
) {
2412 r
= sd_journal_seek_tail(j
);
2414 log_error_errno(r
, "Failed to seek to tail: %m");
2418 r
= sd_journal_previous(j
);
2420 } else if (arg_lines
>= 0) {
2421 r
= sd_journal_seek_tail(j
);
2423 log_error_errno(r
, "Failed to seek to tail: %m");
2427 r
= sd_journal_previous_skip(j
, arg_lines
);
2430 r
= sd_journal_seek_head(j
);
2432 log_error_errno(r
, "Failed to seek to head: %m");
2436 r
= sd_journal_next(j
);
2440 log_error_errno(r
, "Failed to iterate through journal: %m");
2447 (void) pager_open(arg_pager_flags
);
2449 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
)) {
2451 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2453 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2455 log_error_errno(r
, "Failed to get cutoff: %m");
2461 printf("-- Logs begin at %s. --\n",
2462 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2464 printf("-- Logs begin at %s, end at %s. --\n",
2465 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2466 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2471 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2473 size_t highlight
[2] = {};
2477 r
= sd_journal_next(j
);
2479 r
= sd_journal_previous(j
);
2481 log_error_errno(r
, "Failed to iterate through journal: %m");
2488 if (arg_until_set
&& !arg_reverse
) {
2491 r
= sd_journal_get_realtime_usec(j
, &usec
);
2493 log_error_errno(r
, "Failed to determine timestamp: %m");
2496 if (usec
> arg_until
)
2500 if (arg_since_set
&& arg_reverse
) {
2503 r
= sd_journal_get_realtime_usec(j
, &usec
);
2505 log_error_errno(r
, "Failed to determine timestamp: %m");
2508 if (usec
< arg_since
)
2512 if (!arg_merge
&& !arg_quiet
) {
2515 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2517 if (previous_boot_id_valid
&&
2518 !sd_id128_equal(boot_id
, previous_boot_id
))
2519 printf("%s-- Reboot --%s\n",
2520 ansi_highlight(), ansi_normal());
2522 previous_boot_id
= boot_id
;
2523 previous_boot_id_valid
= true;
2528 if (arg_compiled_pattern
) {
2529 _cleanup_(pcre2_match_data_freep
) pcre2_match_data
*md
= NULL
;
2530 const void *message
;
2534 md
= pcre2_match_data_create(1, NULL
);
2538 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2545 log_error_errno(r
, "Failed to get MESSAGE field: %m");
2549 assert_se(message
= startswith(message
, "MESSAGE="));
2551 r
= pcre2_match(arg_compiled_pattern
,
2553 len
- strlen("MESSAGE="),
2554 0, /* start at offset 0 in the subject */
2555 0, /* default options */
2558 if (r
== PCRE2_ERROR_NOMATCH
) {
2563 unsigned char buf
[LINE_MAX
];
2566 r2
= pcre2_get_error_message(r
, buf
, sizeof buf
);
2567 log_error("Pattern matching failed: %s",
2568 r2
< 0 ? "unknown error" : (char*) buf
);
2573 ovec
= pcre2_get_ovector_pointer(md
);
2574 highlight
[0] = ovec
[0];
2575 highlight
[1] = ovec
[1];
2580 arg_all
* OUTPUT_SHOW_ALL
|
2581 arg_full
* OUTPUT_FULL_WIDTH
|
2582 colors_enabled() * OUTPUT_COLOR
|
2583 arg_catalog
* OUTPUT_CATALOG
|
2584 arg_utc
* OUTPUT_UTC
|
2585 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2587 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2588 arg_output_fields
, highlight
, &ellipsized
);
2590 if (r
== -EADDRNOTAVAIL
)
2597 /* If journalctl take a long time to process messages, and during that time journal file
2598 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2599 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2600 * in the "following" case. By periodically calling sd_journal_process() during the processing
2601 * loop we shrink the window of time a client instance has open file descriptors for rotated
2602 * (deleted) journal files. */
2603 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2604 r
= sd_journal_process(j
);
2606 log_error_errno(r
, "Failed to process inotify events: %m");
2613 if (n_shown
== 0 && !arg_quiet
)
2614 printf("-- No entries --\n");
2620 r
= wait_for_change(j
, poll_fd
);
2627 if (arg_show_cursor
|| arg_cursor_file
) {
2628 _cleanup_free_
char *cursor
= NULL
;
2630 r
= sd_journal_get_cursor(j
, &cursor
);
2631 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2632 log_error_errno(r
, "Failed to get cursor: %m");
2634 if (arg_show_cursor
)
2635 printf("-- cursor: %s\n", cursor
);
2637 if (arg_cursor_file
) {
2638 r
= write_string_file(arg_cursor_file
, cursor
,
2639 WRITE_STRING_FILE_CREATE
|
2640 WRITE_STRING_FILE_ATOMIC
);
2643 "Failed to write new cursor to %s: %m",
2652 strv_free(arg_file
);
2654 strv_free(arg_syslog_identifier
);
2655 strv_free(arg_system_units
);
2656 strv_free(arg_user_units
);
2657 strv_free(arg_output_fields
);
2660 free(arg_verify_key
);
2663 if (arg_compiled_pattern
) {
2664 pcre2_code_free(arg_compiled_pattern
);
2666 /* --grep was used, no error was thrown, but the pattern didn't
2667 * match anything. Let's mimic grep's behavior here and return
2668 * a non-zero exit code, so journalctl --grep can be used
2669 * in scripts and such */
2670 if (r
== 0 && n_shown
== 0)
2675 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;