1 /* SPDX-License-Identifier: LGPL-2.1+ */
15 #include <sys/inotify.h>
20 # define PCRE2_CODE_UNIT_WIDTH 8
25 #include "sd-device.h"
26 #include "sd-journal.h"
29 #include "alloc-util.h"
30 #include "bus-error.h"
33 #include "chattr-util.h"
35 #include "device-private.h"
40 #include "glob-util.h"
41 #include "hostname-util.h"
42 #include "id128-print.h"
44 #include "journal-def.h"
45 #include "journal-internal.h"
46 #include "journal-qrcode.h"
47 #include "journal-util.h"
48 #include "journal-vacuum.h"
49 #include "journal-verify.h"
50 #include "locale-util.h"
52 #include "logs-show.h"
55 #include "parse-util.h"
56 #include "path-util.h"
57 #include "rlimit-util.h"
60 #include "string-table.h"
62 #include "syslog-util.h"
63 #include "terminal-util.h"
64 #include "unit-name.h"
65 #include "user-util.h"
67 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
69 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
72 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data
*, pcre2_match_data_free
);
73 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code
*, pcre2_code_free
);
75 static int pattern_compile(const char *pattern
, unsigned flags
, pcre2_code
**out
) {
77 PCRE2_SIZE erroroffset
;
80 p
= pcre2_compile((PCRE2_SPTR8
) pattern
,
81 PCRE2_ZERO_TERMINATED
, flags
, &errorcode
, &erroroffset
, NULL
);
83 unsigned char buf
[LINE_MAX
];
85 r
= pcre2_get_error_message(errorcode
, buf
, sizeof buf
);
87 log_error("Bad pattern \"%s\": %s",
89 r
< 0 ? "unknown error" : (char*) buf
);
100 /* Special values for arg_lines */
101 ARG_LINES_DEFAULT
= -2,
105 static OutputMode arg_output
= OUTPUT_SHORT
;
106 static bool arg_utc
= false;
107 static bool arg_pager_end
= false;
108 static bool arg_follow
= false;
109 static bool arg_full
= true;
110 static bool arg_all
= false;
111 static bool arg_no_pager
= false;
112 static int arg_lines
= ARG_LINES_DEFAULT
;
113 static bool arg_no_tail
= false;
114 static bool arg_quiet
= false;
115 static bool arg_merge
= false;
116 static bool arg_boot
= false;
117 static sd_id128_t arg_boot_id
= {};
118 static int arg_boot_offset
= 0;
119 static bool arg_dmesg
= false;
120 static bool arg_no_hostname
= false;
121 static const char *arg_cursor
= NULL
;
122 static const char *arg_after_cursor
= NULL
;
123 static bool arg_show_cursor
= false;
124 static const char *arg_directory
= NULL
;
125 static char **arg_file
= NULL
;
126 static bool arg_file_stdin
= false;
127 static int arg_priorities
= 0xFF;
128 static char *arg_verify_key
= NULL
;
130 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
131 static bool arg_force
= false;
133 static usec_t arg_since
, arg_until
;
134 static bool arg_since_set
= false, arg_until_set
= false;
135 static char **arg_syslog_identifier
= NULL
;
136 static char **arg_system_units
= NULL
;
137 static char **arg_user_units
= NULL
;
138 static const char *arg_field
= NULL
;
139 static bool arg_catalog
= false;
140 static bool arg_reverse
= false;
141 static int arg_journal_type
= 0;
142 static char *arg_root
= NULL
;
143 static const char *arg_machine
= NULL
;
144 static uint64_t arg_vacuum_size
= 0;
145 static uint64_t arg_vacuum_n_files
= 0;
146 static usec_t arg_vacuum_time
= 0;
147 static char **arg_output_fields
= NULL
;
150 static const char *arg_pattern
= NULL
;
151 static pcre2_code
*arg_compiled_pattern
= NULL
;
152 static int arg_case_sensitive
= -1; /* -1 means be smart */
164 ACTION_UPDATE_CATALOG
,
171 ACTION_LIST_FIELD_NAMES
,
172 } arg_action
= ACTION_SHOW
;
174 typedef struct BootId
{
178 LIST_FIELDS(struct BootId
, boot_list
);
181 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
182 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
190 if (!path_startswith(devpath
, "/dev/")) {
191 log_error("Devpath does not start with /dev/");
195 if (stat(devpath
, &st
) < 0)
196 return log_error_errno(errno
, "Couldn't stat file: %m");
198 r
= device_new_from_stat_rdev(&device
, &st
);
200 return log_error_errno(r
, "Failed to get device from devnum %u:%u: %m", major(st
.st_rdev
), minor(st
.st_rdev
));
202 for (d
= device
; d
; ) {
203 _cleanup_free_
char *match
= NULL
;
204 const char *subsys
, *sysname
, *devnode
;
207 r
= sd_device_get_subsystem(d
, &subsys
);
211 r
= sd_device_get_sysname(d
, &sysname
);
215 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
219 r
= sd_journal_add_match(j
, match
, 0);
221 return log_error_errno(r
, "Failed to add match: %m");
223 if (sd_device_get_devname(d
, &devnode
) >= 0) {
224 _cleanup_free_
char *match1
= NULL
;
226 r
= stat(devnode
, &st
);
228 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
230 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st
.st_mode
) ? 'b' : 'c', major(st
.st_rdev
), minor(st
.st_rdev
));
234 r
= sd_journal_add_match(j
, match1
, 0);
236 return log_error_errno(r
, "Failed to add match: %m");
240 if (sd_device_get_parent(d
, &parent
) < 0)
246 r
= add_match_this_boot(j
, arg_machine
);
248 return log_error_errno(r
, "Failed to add match for the current boot: %m");
253 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
256 return format_timestamp_utc(buf
, l
, t
);
258 return format_timestamp(buf
, l
, t
);
261 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
262 sd_id128_t id
= SD_ID128_NULL
;
265 if (strlen(x
) >= 32) {
269 r
= sd_id128_from_string(t
, &id
);
273 if (!IN_SET(*x
, 0, '-', '+'))
277 r
= safe_atoi(x
, &off
);
282 r
= safe_atoi(x
, &off
);
296 static int help(void) {
297 _cleanup_free_
char *link
= NULL
;
300 (void) pager_open(arg_no_pager
, arg_pager_end
);
302 r
= terminal_urlify_man("journalctl", "1", &link
);
306 printf("%s [OPTIONS...] [MATCHES...]\n\n"
307 "Query the journal.\n\n"
309 " --system Show the system journal\n"
310 " --user Show the user journal for the current user\n"
311 " -M --machine=CONTAINER Operate on local container\n"
312 " -S --since=DATE Show entries not older than the specified date\n"
313 " -U --until=DATE Show entries not newer than the specified date\n"
314 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
315 " --after-cursor=CURSOR Show entries after the specified cursor\n"
316 " --show-cursor Print the cursor after all the entries\n"
317 " -b --boot[=ID] Show current boot or the specified boot\n"
318 " --list-boots Show terse information about recorded boots\n"
319 " -k --dmesg Show kernel message log from the current boot\n"
320 " -u --unit=UNIT Show logs from the specified unit\n"
321 " --user-unit=UNIT Show logs from the specified user unit\n"
322 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
323 " -p --priority=RANGE Show entries with the specified priority\n"
324 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
325 " --case-sensitive[=BOOL] Force case sensitive or insenstive matching\n"
326 " -e --pager-end Immediately jump to the end in the pager\n"
327 " -f --follow Follow the journal\n"
328 " -n --lines[=INTEGER] Number of journal entries to show\n"
329 " --no-tail Show all lines, even in follow mode\n"
330 " -r --reverse Show the newest entries first\n"
331 " -o --output=STRING Change journal output mode (short, short-precise,\n"
332 " short-iso, short-iso-precise, short-full,\n"
333 " short-monotonic, short-unix, verbose, export,\n"
334 " json, json-pretty, json-sse, json-seq, cat,\n"
336 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
337 " --utc Express time in Coordinated Universal Time (UTC)\n"
338 " -x --catalog Add message explanations where available\n"
339 " --no-full Ellipsize fields\n"
340 " -a --all Show all fields, including long and unprintable\n"
341 " -q --quiet Do not show info messages and privilege warning\n"
342 " --no-pager Do not pipe output into a pager\n"
343 " --no-hostname Suppress output of hostname field\n"
344 " -m --merge Show entries from all available journals\n"
345 " -D --directory=PATH Show journal files from directory\n"
346 " --file=PATH Show journal file\n"
347 " --root=ROOT Operate on files below a root directory\n"
348 " --interval=TIME Time interval for changing the FSS sealing key\n"
349 " --verify-key=KEY Specify FSS verification key\n"
350 " --force Override of the FSS key pair with --setup-keys\n"
352 " -h --help Show this help text\n"
353 " --version Show package version\n"
354 " -N --fields List all field names currently used\n"
355 " -F --field=FIELD List all values that a specified field takes\n"
356 " --disk-usage Show total disk usage of all journal files\n"
357 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
358 " --vacuum-files=INT Leave only the specified number of journal files\n"
359 " --vacuum-time=TIME Remove journal files older than specified time\n"
360 " --verify Verify journal file consistency\n"
361 " --sync Synchronize unwritten journal messages to disk\n"
362 " --flush Flush all journal data from /run into /var\n"
363 " --rotate Request immediate rotation of the journal files\n"
364 " --header Show journal header information\n"
365 " --list-catalog Show all message IDs in the catalog\n"
366 " --dump-catalog Show entries in the message catalog\n"
367 " --update-catalog Update the message catalog database\n"
368 " --setup-keys Generate a new FSS key pair\n"
369 "\nSee the %s for details.\n"
370 , program_invocation_short_name
377 static int parse_argv(int argc
, char *argv
[]) {
416 static const struct option options
[] = {
417 { "help", no_argument
, NULL
, 'h' },
418 { "version" , no_argument
, NULL
, ARG_VERSION
},
419 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
420 { "pager-end", no_argument
, NULL
, 'e' },
421 { "follow", no_argument
, NULL
, 'f' },
422 { "force", no_argument
, NULL
, ARG_FORCE
},
423 { "output", required_argument
, NULL
, 'o' },
424 { "all", no_argument
, NULL
, 'a' },
425 { "full", no_argument
, NULL
, 'l' },
426 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
427 { "lines", optional_argument
, NULL
, 'n' },
428 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
429 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
430 { "quiet", no_argument
, NULL
, 'q' },
431 { "merge", no_argument
, NULL
, 'm' },
432 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
433 { "boot", optional_argument
, NULL
, 'b' },
434 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
435 { "dmesg", no_argument
, NULL
, 'k' },
436 { "system", no_argument
, NULL
, ARG_SYSTEM
},
437 { "user", no_argument
, NULL
, ARG_USER
},
438 { "directory", required_argument
, NULL
, 'D' },
439 { "file", required_argument
, NULL
, ARG_FILE
},
440 { "root", required_argument
, NULL
, ARG_ROOT
},
441 { "header", no_argument
, NULL
, ARG_HEADER
},
442 { "identifier", required_argument
, NULL
, 't' },
443 { "priority", required_argument
, NULL
, 'p' },
444 { "grep", required_argument
, NULL
, 'g' },
445 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
446 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
447 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
448 { "verify", no_argument
, NULL
, ARG_VERIFY
},
449 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
450 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
451 { "cursor", required_argument
, NULL
, 'c' },
452 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
453 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
454 { "since", required_argument
, NULL
, 'S' },
455 { "until", required_argument
, NULL
, 'U' },
456 { "unit", required_argument
, NULL
, 'u' },
457 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
458 { "field", required_argument
, NULL
, 'F' },
459 { "fields", no_argument
, NULL
, 'N' },
460 { "catalog", no_argument
, NULL
, 'x' },
461 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
462 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
463 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
464 { "reverse", no_argument
, NULL
, 'r' },
465 { "machine", required_argument
, NULL
, 'M' },
466 { "utc", no_argument
, NULL
, ARG_UTC
},
467 { "flush", no_argument
, NULL
, ARG_FLUSH
},
468 { "sync", no_argument
, NULL
, ARG_SYNC
},
469 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
470 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
471 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
472 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
473 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
474 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
483 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
498 arg_pager_end
= true;
500 if (arg_lines
== ARG_LINES_DEFAULT
)
510 if (streq(optarg
, "help")) {
511 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
515 arg_output
= output_mode_from_string(optarg
);
516 if (arg_output
< 0) {
517 log_error("Unknown output format '%s'.", optarg
);
521 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
540 if (streq(optarg
, "all"))
541 arg_lines
= ARG_LINES_ALL
;
543 r
= safe_atoi(optarg
, &arg_lines
);
544 if (r
< 0 || arg_lines
< 0) {
545 log_error("Failed to parse lines '%s'", optarg
);
552 /* Hmm, no argument? Maybe the next
553 * word on the command line is
554 * supposed to be the argument? Let's
555 * see if there is one, and is
559 if (streq(argv
[optind
], "all")) {
560 arg_lines
= ARG_LINES_ALL
;
562 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
576 arg_action
= ACTION_NEW_ID128
;
595 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
597 log_error("Failed to parse boot descriptor '%s'", optarg
);
602 /* Hmm, no argument? Maybe the next
603 * word on the command line is
604 * supposed to be the argument? Let's
605 * see if there is one and is parsable
606 * as a boot descriptor... */
609 parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
) >= 0)
616 arg_action
= ACTION_LIST_BOOTS
;
620 arg_boot
= arg_dmesg
= true;
624 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
628 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
632 arg_machine
= optarg
;
636 arg_directory
= optarg
;
640 if (streq(optarg
, "-"))
641 /* An undocumented feature: we can read journal files from STDIN. We don't document
642 * this though, since after all we only support this for mmap-able, seekable files, and
643 * not for example pipes which are probably the primary usecase for reading things from
644 * STDIN. To avoid confusion we hence don't document this feature. */
645 arg_file_stdin
= true;
647 r
= glob_extend(&arg_file
, optarg
);
649 return log_error_errno(r
, "Failed to add paths: %m");
654 r
= parse_path_argument_and_warn(optarg
, true, &arg_root
);
663 case ARG_AFTER_CURSOR
:
664 arg_after_cursor
= optarg
;
667 case ARG_SHOW_CURSOR
:
668 arg_show_cursor
= true;
672 arg_action
= ACTION_PRINT_HEADER
;
676 arg_action
= ACTION_VERIFY
;
680 arg_action
= ACTION_DISK_USAGE
;
683 case ARG_VACUUM_SIZE
:
684 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
686 log_error("Failed to parse vacuum size: %s", optarg
);
690 arg_action
= ACTION_VACUUM
;
693 case ARG_VACUUM_FILES
:
694 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
696 log_error("Failed to parse vacuum files: %s", optarg
);
700 arg_action
= ACTION_VACUUM
;
703 case ARG_VACUUM_TIME
:
704 r
= parse_sec(optarg
, &arg_vacuum_time
);
706 log_error("Failed to parse vacuum time: %s", optarg
);
710 arg_action
= ACTION_VACUUM
;
719 arg_action
= ACTION_SETUP_KEYS
;
723 arg_action
= ACTION_VERIFY
;
724 r
= free_and_strdup(&arg_verify_key
, optarg
);
727 /* Use memset not string_erase so this doesn't look confusing
728 * in ps or htop output. */
729 memset(optarg
, 'x', strlen(optarg
));
735 r
= parse_sec(optarg
, &arg_interval
);
736 if (r
< 0 || arg_interval
<= 0) {
737 log_error("Failed to parse sealing key change interval: %s", optarg
);
746 log_error("Compiled without forward-secure sealing support.");
753 dots
= strstr(optarg
, "..");
759 a
= strndup(optarg
, dots
- optarg
);
763 from
= log_level_from_string(a
);
764 to
= log_level_from_string(dots
+ 2);
767 if (from
< 0 || to
< 0) {
768 log_error("Failed to parse log level range %s", optarg
);
775 for (i
= from
; i
<= to
; i
++)
776 arg_priorities
|= 1 << i
;
778 for (i
= to
; i
<= from
; i
++)
779 arg_priorities
|= 1 << i
;
785 p
= log_level_from_string(optarg
);
787 log_error("Unknown log level %s", optarg
);
793 for (i
= 0; i
<= p
; i
++)
794 arg_priorities
|= 1 << i
;
802 arg_pattern
= optarg
;
805 case ARG_CASE_SENSITIVE
:
807 r
= parse_boolean(optarg
);
809 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
810 arg_case_sensitive
= r
;
812 arg_case_sensitive
= true;
817 case ARG_CASE_SENSITIVE
:
818 return log_error("Compiled without pattern matching support");
822 r
= parse_timestamp(optarg
, &arg_since
);
824 log_error("Failed to parse timestamp: %s", optarg
);
827 arg_since_set
= true;
831 r
= parse_timestamp(optarg
, &arg_until
);
833 log_error("Failed to parse timestamp: %s", optarg
);
836 arg_until_set
= true;
840 r
= strv_extend(&arg_syslog_identifier
, optarg
);
846 r
= strv_extend(&arg_system_units
, optarg
);
852 r
= strv_extend(&arg_user_units
, optarg
);
858 arg_action
= ACTION_LIST_FIELDS
;
863 arg_action
= ACTION_LIST_FIELD_NAMES
;
866 case ARG_NO_HOSTNAME
:
867 arg_no_hostname
= true;
874 case ARG_LIST_CATALOG
:
875 arg_action
= ACTION_LIST_CATALOG
;
878 case ARG_DUMP_CATALOG
:
879 arg_action
= ACTION_DUMP_CATALOG
;
882 case ARG_UPDATE_CATALOG
:
883 arg_action
= ACTION_UPDATE_CATALOG
;
895 arg_action
= ACTION_FLUSH
;
899 arg_action
= ACTION_ROTATE
;
903 arg_action
= ACTION_SYNC
;
906 case ARG_OUTPUT_FIELDS
: {
907 _cleanup_strv_free_
char **v
= NULL
;
909 v
= strv_split(optarg
, ",");
913 if (!arg_output_fields
)
914 arg_output_fields
= TAKE_PTR(v
);
916 r
= strv_extend_strv(&arg_output_fields
, v
, true);
927 assert_not_reached("Unhandled option");
930 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
933 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
> 1) {
934 log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root.");
938 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
) {
939 log_error("--since= must be before --until=.");
943 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1) {
944 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
948 if (arg_follow
&& arg_reverse
) {
949 log_error("Please specify either --reverse= or --follow=, not both.");
953 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
) {
954 log_error("Extraneous arguments starting with '%s'", argv
[optind
]);
958 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
) {
959 log_error("Using --boot or --list-boots with --merge is not supported.");
963 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
964 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
965 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
966 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
967 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
971 arg_system_units
= strv_free(arg_system_units
);
978 if (arg_case_sensitive
>= 0)
979 flags
= !arg_case_sensitive
* PCRE2_CASELESS
;
981 _cleanup_(pcre2_match_data_freep
) pcre2_match_data
*md
= NULL
;
983 _cleanup_(pcre2_code_freep
) pcre2_code
*cs
= NULL
;
985 md
= pcre2_match_data_create(1, NULL
);
989 r
= pattern_compile("[[:upper:]]", 0, &cs
);
993 r
= pcre2_match(cs
, (PCRE2_SPTR8
) arg_pattern
, PCRE2_ZERO_TERMINATED
, 0, 0, md
, NULL
);
996 flags
= !has_case
* PCRE2_CASELESS
;
999 log_debug("Doing case %s matching based on %s",
1000 flags
& PCRE2_CASELESS
? "insensitive" : "sensitive",
1001 arg_case_sensitive
>= 0 ? "request" : "pattern casing");
1003 r
= pattern_compile(arg_pattern
, flags
, &arg_compiled_pattern
);
1012 static int add_matches(sd_journal
*j
, char **args
) {
1014 bool have_term
= false;
1018 STRV_FOREACH(i
, args
) {
1021 if (streq(*i
, "+")) {
1024 r
= sd_journal_add_disjunction(j
);
1027 } else if (path_is_absolute(*i
)) {
1028 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1031 r
= chase_symlinks(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
);
1033 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1035 if (lstat(p
, &st
) < 0)
1036 return log_error_errno(errno
, "Couldn't stat file: %m");
1038 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1039 if (executable_is_script(p
, &interpreter
) > 0) {
1040 _cleanup_free_
char *comm
;
1042 comm
= strndup(basename(p
), 15);
1046 t
= strappend("_COMM=", comm
);
1050 /* Append _EXE only if the interpreter is not a link.
1051 Otherwise, it might be outdated often. */
1052 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1053 t2
= strappend("_EXE=", interpreter
);
1058 t
= strappend("_EXE=", p
);
1063 r
= sd_journal_add_match(j
, t
, 0);
1066 r
= sd_journal_add_match(j
, t2
, 0);
1068 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1069 r
= add_matches_for_device(j
, p
);
1073 log_error("File is neither a device node, nor regular file, nor executable: %s", *i
);
1079 r
= sd_journal_add_match(j
, *i
, 0);
1084 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1087 if (!strv_isempty(args
) && !have_term
) {
1088 log_error("\"+\" can only be used between terms");
1095 static void boot_id_free_all(BootId
*l
) {
1099 LIST_REMOVE(boot_list
, l
, i
);
1104 static int discover_next_boot(sd_journal
*j
,
1105 sd_id128_t previous_boot_id
,
1109 _cleanup_free_ BootId
*next_boot
= NULL
;
1110 char match
[9+32+1] = "_BOOT_ID=";
1117 /* We expect the journal to be on the last position of a boot
1118 * (in relation to the direction we are going), so that the next
1119 * invocation of sd_journal_next/previous will be from a different
1120 * boot. We then collect any information we desire and then jump
1121 * to the last location of the new boot by using a _BOOT_ID match
1122 * coming from the other journal direction. */
1124 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1125 * we can actually advance to a *different* boot. */
1126 sd_journal_flush_matches(j
);
1130 r
= sd_journal_previous(j
);
1132 r
= sd_journal_next(j
);
1136 return 0; /* End of journal, yay. */
1138 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1142 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1143 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1144 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1145 * complete than the main entry array, and hence might reference an entry that's not actually the last
1146 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1147 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1150 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1152 next_boot
= new0(BootId
, 1);
1156 next_boot
->id
= boot_id
;
1158 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1162 /* Now seek to the last occurrence of this boot ID. */
1163 sd_id128_to_string(next_boot
->id
, match
+ 9);
1164 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1169 r
= sd_journal_seek_head(j
);
1171 r
= sd_journal_seek_tail(j
);
1176 r
= sd_journal_next(j
);
1178 r
= sd_journal_previous(j
);
1182 log_debug("Whoopsie! We found a boot ID but can't read its last entry.");
1183 return -ENODATA
; /* This shouldn't happen. We just came from this very boot ID. */
1186 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1190 *ret
= TAKE_PTR(next_boot
);
1195 static int get_boots(
1198 sd_id128_t
*boot_id
,
1203 BootId
*head
= NULL
, *tail
= NULL
, *id
;
1204 const bool advance_older
= boot_id
&& offset
<= 0;
1205 sd_id128_t previous_boot_id
;
1209 /* Adjust for the asymmetry that offset 0 is
1210 * the last (and current) boot, while 1 is considered the
1211 * (chronological) first boot in the journal. */
1212 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1214 /* Advance to the earliest/latest occurrence of our reference
1215 * boot ID (taking our lookup direction into account), so that
1216 * discover_next_boot() can do its job.
1217 * If no reference is given, the journal head/tail will do,
1218 * they're "virtual" boots after all. */
1219 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1220 char match
[9+32+1] = "_BOOT_ID=";
1222 sd_journal_flush_matches(j
);
1224 sd_id128_to_string(*boot_id
, match
+ 9);
1225 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1230 r
= sd_journal_seek_head(j
); /* seek to oldest */
1232 r
= sd_journal_seek_tail(j
); /* seek to newest */
1237 r
= sd_journal_next(j
); /* read the oldest entry */
1239 r
= sd_journal_previous(j
); /* read the most recently added entry */
1244 else if (offset
== 0) {
1249 /* At this point the read pointer is positioned at the oldest/newest occurence of the reference boot
1250 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1251 * the following entry, which must then have an older/newer boot ID */
1255 r
= sd_journal_seek_tail(j
); /* seek to newest */
1257 r
= sd_journal_seek_head(j
); /* seek to oldest */
1261 /* No sd_journal_next()/_previous() here.
1263 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1264 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1268 previous_boot_id
= SD_ID128_NULL
;
1270 _cleanup_free_ BootId
*current
= NULL
;
1272 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1274 boot_id_free_all(head
);
1281 previous_boot_id
= current
->id
;
1285 offset
+= advance_older
? 1 : -1;
1290 *boot_id
= current
->id
;
1294 LIST_FOREACH(boot_list
, id
, head
) {
1295 if (sd_id128_equal(id
->id
, current
->id
)) {
1296 /* boot id already stored, something wrong with the journal files */
1297 /* exiting as otherwise this problem would cause forever loop */
1301 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1302 tail
= TAKE_PTR(current
);
1311 sd_journal_flush_matches(j
);
1316 static int list_boots(sd_journal
*j
) {
1318 BootId
*id
, *all_ids
;
1322 count
= get_boots(j
, &all_ids
, NULL
, 0);
1324 return log_error_errno(count
, "Failed to determine boots: %m");
1328 (void) pager_open(arg_no_pager
, arg_pager_end
);
1330 /* numbers are one less, but we need an extra char for the sign */
1331 w
= DECIMAL_STR_WIDTH(count
- 1) + 1;
1334 LIST_FOREACH(boot_list
, id
, all_ids
) {
1335 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1337 printf("% *i " SD_ID128_FORMAT_STR
" %s—%s\n",
1339 SD_ID128_FORMAT_VAL(id
->id
),
1340 format_timestamp_maybe_utc(a
, sizeof(a
), id
->first
),
1341 format_timestamp_maybe_utc(b
, sizeof(b
), id
->last
));
1345 boot_id_free_all(all_ids
);
1350 static int add_boot(sd_journal
*j
) {
1351 char match
[9+32+1] = "_BOOT_ID=";
1360 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1361 * We can do this only when we logs are coming from the current machine,
1362 * so take the slow path if log location is specified. */
1363 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1364 !arg_directory
&& !arg_file
&& !arg_root
)
1366 return add_match_this_boot(j
, arg_machine
);
1368 boot_id
= arg_boot_id
;
1369 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1372 const char *reason
= (r
== 0) ? "No such boot ID in journal" : strerror(-r
);
1374 if (sd_id128_is_null(arg_boot_id
))
1375 log_error("Data from the specified boot (%+i) is not available: %s",
1376 arg_boot_offset
, reason
);
1378 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1379 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1381 return r
== 0 ? -ENODATA
: r
;
1384 sd_id128_to_string(boot_id
, match
+ 9);
1386 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1388 return log_error_errno(r
, "Failed to add match: %m");
1390 r
= sd_journal_add_conjunction(j
);
1392 return log_error_errno(r
, "Failed to add conjunction: %m");
1397 static int add_dmesg(sd_journal
*j
) {
1404 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1405 STRLEN("_TRANSPORT=kernel"));
1407 return log_error_errno(r
, "Failed to add match: %m");
1409 r
= sd_journal_add_conjunction(j
);
1411 return log_error_errno(r
, "Failed to add conjunction: %m");
1416 static int get_possible_units(
1422 _cleanup_set_free_free_ Set
*found
;
1426 found
= set_new(&string_hash_ops
);
1430 NULSTR_FOREACH(field
, fields
) {
1434 r
= sd_journal_query_unique(j
, field
);
1438 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1439 char **pattern
, *eq
;
1441 _cleanup_free_
char *u
= NULL
;
1443 eq
= memchr(data
, '=', size
);
1445 prefix
= eq
- (char*) data
+ 1;
1449 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1453 STRV_FOREACH(pattern
, patterns
)
1454 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1455 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1457 r
= set_consume(found
, u
);
1459 if (r
< 0 && r
!= -EEXIST
)
1467 *units
= TAKE_PTR(found
);
1472 /* This list is supposed to return the superset of unit names
1473 * possibly matched by rules added with add_matches_for_unit... */
1474 #define SYSTEM_UNITS \
1478 "OBJECT_SYSTEMD_UNIT\0" \
1481 /* ... and add_matches_for_user_unit */
1482 #define USER_UNITS \
1483 "_SYSTEMD_USER_UNIT\0" \
1485 "COREDUMP_USER_UNIT\0" \
1486 "OBJECT_SYSTEMD_USER_UNIT\0"
1488 static int add_units(sd_journal
*j
) {
1489 _cleanup_strv_free_
char **patterns
= NULL
;
1495 STRV_FOREACH(i
, arg_system_units
) {
1496 _cleanup_free_
char *u
= NULL
;
1498 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1502 if (string_is_glob(u
)) {
1503 r
= strv_push(&patterns
, u
);
1508 r
= add_matches_for_unit(j
, u
);
1511 r
= sd_journal_add_disjunction(j
);
1518 if (!strv_isempty(patterns
)) {
1519 _cleanup_set_free_free_ Set
*units
= NULL
;
1523 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1527 SET_FOREACH(u
, units
, it
) {
1528 r
= add_matches_for_unit(j
, u
);
1531 r
= sd_journal_add_disjunction(j
);
1538 patterns
= strv_free(patterns
);
1540 STRV_FOREACH(i
, arg_user_units
) {
1541 _cleanup_free_
char *u
= NULL
;
1543 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1547 if (string_is_glob(u
)) {
1548 r
= strv_push(&patterns
, u
);
1553 r
= add_matches_for_user_unit(j
, u
, getuid());
1556 r
= sd_journal_add_disjunction(j
);
1563 if (!strv_isempty(patterns
)) {
1564 _cleanup_set_free_free_ Set
*units
= NULL
;
1568 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1572 SET_FOREACH(u
, units
, it
) {
1573 r
= add_matches_for_user_unit(j
, u
, getuid());
1576 r
= sd_journal_add_disjunction(j
);
1583 /* Complain if the user request matches but nothing whatsoever was
1584 * found, since otherwise everything would be matched. */
1585 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1588 r
= sd_journal_add_conjunction(j
);
1595 static int add_priorities(sd_journal
*j
) {
1596 char match
[] = "PRIORITY=0";
1600 if (arg_priorities
== 0xFF)
1603 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1604 if (arg_priorities
& (1 << i
)) {
1605 match
[sizeof(match
)-2] = '0' + i
;
1607 r
= sd_journal_add_match(j
, match
, strlen(match
));
1609 return log_error_errno(r
, "Failed to add match: %m");
1612 r
= sd_journal_add_conjunction(j
);
1614 return log_error_errno(r
, "Failed to add conjunction: %m");
1619 static int add_syslog_identifier(sd_journal
*j
) {
1625 STRV_FOREACH(i
, arg_syslog_identifier
) {
1628 u
= strjoina("SYSLOG_IDENTIFIER=", *i
);
1629 r
= sd_journal_add_match(j
, u
, 0);
1632 r
= sd_journal_add_disjunction(j
);
1637 r
= sd_journal_add_conjunction(j
);
1644 static int setup_keys(void) {
1646 size_t mpk_size
, seed_size
, state_size
, i
;
1647 uint8_t *mpk
, *seed
, *state
;
1649 sd_id128_t machine
, boot
;
1650 char *p
= NULL
, *k
= NULL
;
1655 r
= stat("/var/log/journal", &st
);
1656 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1657 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1659 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1660 log_error("%s is not a directory, must be using persistent logging for FSS.",
1661 "/var/log/journal");
1662 return r
< 0 ? -errno
: -ENOTDIR
;
1665 r
= sd_id128_get_machine(&machine
);
1667 return log_error_errno(r
, "Failed to get machine ID: %m");
1669 r
= sd_id128_get_boot(&boot
);
1671 return log_error_errno(r
, "Failed to get boot ID: %m");
1673 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1674 SD_ID128_FORMAT_VAL(machine
)) < 0)
1679 if (r
< 0 && errno
!= ENOENT
) {
1680 r
= log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1683 } else if (access(p
, F_OK
) >= 0) {
1684 log_error("Sealing key file %s exists already. Use --force to recreate.", p
);
1689 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1690 SD_ID128_FORMAT_VAL(machine
)) < 0) {
1695 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1696 mpk
= alloca(mpk_size
);
1698 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1699 seed
= alloca(seed_size
);
1701 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1702 state
= alloca(state_size
);
1704 fd
= open("/dev/random", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1706 r
= log_error_errno(errno
, "Failed to open /dev/random: %m");
1710 log_info("Generating seed...");
1711 r
= loop_read_exact(fd
, seed
, seed_size
, true);
1713 log_error_errno(r
, "Failed to read random seed: %m");
1717 log_info("Generating key pair...");
1718 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1720 log_info("Generating sealing key...");
1721 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1723 assert(arg_interval
> 0);
1725 n
= now(CLOCK_REALTIME
);
1729 fd
= mkostemp_safe(k
);
1731 r
= log_error_errno(fd
, "Failed to open %s: %m", k
);
1735 /* Enable secure remove, exclusion from dump, synchronous
1736 * writing and in-place updating */
1737 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
);
1739 log_warning_errno(r
, "Failed to set file attributes: %m");
1742 memcpy(h
.signature
, "KSHHRHLP", 8);
1743 h
.machine_id
= machine
;
1745 h
.header_size
= htole64(sizeof(h
));
1746 h
.start_usec
= htole64(n
* arg_interval
);
1747 h
.interval_usec
= htole64(arg_interval
);
1748 h
.fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
);
1749 h
.fsprg_state_size
= htole64(state_size
);
1751 r
= loop_write(fd
, &h
, sizeof(h
), false);
1753 log_error_errno(r
, "Failed to write header: %m");
1757 r
= loop_write(fd
, state
, state_size
, false);
1759 log_error_errno(r
, "Failed to write state: %m");
1763 if (link(k
, p
) < 0) {
1764 r
= log_error_errno(errno
, "Failed to link file: %m");
1771 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1772 "the following local file. This key file is automatically updated when the\n"
1773 "sealing key is advanced. It should not be used on multiple hosts.\n"
1777 "Please write down the following %ssecret verification key%s. It should be stored\n"
1778 "at a safe location and should not be saved locally on disk.\n"
1780 ansi_highlight(), ansi_normal(),
1782 ansi_highlight(), ansi_normal(),
1783 ansi_highlight_red());
1786 for (i
= 0; i
< seed_size
; i
++) {
1787 if (i
> 0 && i
% 3 == 0)
1789 printf("%02x", ((uint8_t*) seed
)[i
]);
1792 printf("/%llx-%llx\n", (unsigned long long) n
, (unsigned long long) arg_interval
);
1795 char tsb
[FORMAT_TIMESPAN_MAX
], *hn
;
1799 "The sealing key is automatically changed every %s.\n",
1801 format_timespan(tsb
, sizeof(tsb
), arg_interval
, 0));
1803 hn
= gethostname_malloc();
1806 hostname_cleanup(hn
);
1807 fprintf(stderr
, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR
".\n", hn
, SD_ID128_FORMAT_VAL(machine
));
1809 fprintf(stderr
, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR
".\n", SD_ID128_FORMAT_VAL(machine
));
1812 /* If this is not an UTF-8 system don't print any QR codes */
1813 if (is_locale_utf8()) {
1814 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr
);
1815 print_qr_code(stderr
, seed
, seed_size
, n
, arg_interval
, hn
, machine
);
1835 log_error("Forward-secure sealing not available.");
1840 static int verify(sd_journal
*j
) {
1847 log_show_color(true);
1849 ORDERED_HASHMAP_FOREACH(f
, j
->files
, i
) {
1851 usec_t first
= 0, validated
= 0, last
= 0;
1854 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1855 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1858 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, true);
1860 /* If the key was invalid give up right-away. */
1863 log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1866 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
], c
[FORMAT_TIMESPAN_MAX
];
1867 log_info("PASS: %s", f
->path
);
1869 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1870 if (validated
> 0) {
1871 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1872 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1873 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1874 format_timespan(c
, sizeof(c
), last
> validated
? last
- validated
: 0, 0));
1875 } else if (last
> 0)
1876 log_info("=> No sealing yet, %s of entries not sealed.",
1877 format_timespan(c
, sizeof(c
), last
- first
, 0));
1879 log_info("=> No sealing yet, no entries in file.");
1887 static int flush_to_var(void) {
1888 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1889 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1890 _cleanup_close_
int watch_fd
= -1;
1894 log_error("--flush is not supported in conjunction with --machine=.");
1899 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1902 /* OK, let's actually do the full logic, send SIGUSR1 to the
1903 * daemon and set up inotify to wait for the flushed file to appear */
1904 r
= bus_connect_system_systemd(&bus
);
1906 return log_error_errno(r
, "Failed to get D-Bus connection: %m");
1908 r
= sd_bus_call_method(
1910 "org.freedesktop.systemd1",
1911 "/org/freedesktop/systemd1",
1912 "org.freedesktop.systemd1.Manager",
1916 "ssi", "systemd-journald.service", "main", SIGUSR1
);
1918 return log_error_errno(r
, "Failed to kill journal service: %s", bus_error_message(&error
, r
));
1920 mkdir_p("/run/systemd/journal", 0755);
1922 watch_fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
1924 return log_error_errno(errno
, "Failed to create inotify watch: %m");
1926 r
= inotify_add_watch(watch_fd
, "/run/systemd/journal", IN_CREATE
|IN_DONT_FOLLOW
|IN_ONLYDIR
);
1928 return log_error_errno(errno
, "Failed to watch journal directory: %m");
1931 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1934 if (errno
!= ENOENT
)
1935 return log_error_errno(errno
, "Failed to check for existence of /run/systemd/journal/flushed: %m");
1937 r
= fd_wait_for_event(watch_fd
, POLLIN
, USEC_INFINITY
);
1939 return log_error_errno(r
, "Failed to wait for event: %m");
1941 r
= flush_fd(watch_fd
);
1943 return log_error_errno(r
, "Failed to flush inotify events: %m");
1949 static int send_signal_and_wait(int sig
, const char *watch_path
) {
1950 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1951 _cleanup_close_
int watch_fd
= -1;
1956 log_error("--sync and --rotate are not supported in conjunction with --machine=.");
1960 start
= now(CLOCK_MONOTONIC
);
1962 /* This call sends the specified signal to journald, and waits
1963 * for acknowledgment by watching the mtime of the specified
1964 * flag file. This is used to trigger syncing or rotation and
1965 * then wait for the operation to complete. */
1970 /* See if a sync happened by now. */
1971 r
= read_timestamp_file(watch_path
, &tstamp
);
1972 if (r
< 0 && r
!= -ENOENT
)
1973 return log_error_errno(errno
, "Failed to read %s: %m", watch_path
);
1974 if (r
>= 0 && tstamp
>= start
)
1977 /* Let's ask for a sync, but only once. */
1979 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1981 r
= bus_connect_system_systemd(&bus
);
1983 return log_error_errno(r
, "Failed to get D-Bus connection: %m");
1985 r
= sd_bus_call_method(
1987 "org.freedesktop.systemd1",
1988 "/org/freedesktop/systemd1",
1989 "org.freedesktop.systemd1.Manager",
1993 "ssi", "systemd-journald.service", "main", sig
);
1995 return log_error_errno(r
, "Failed to kill journal service: %s", bus_error_message(&error
, r
));
2000 /* Let's install the inotify watch, if we didn't do that yet. */
2003 mkdir_p("/run/systemd/journal", 0755);
2005 watch_fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
2007 return log_error_errno(errno
, "Failed to create inotify watch: %m");
2009 r
= inotify_add_watch(watch_fd
, "/run/systemd/journal", IN_MOVED_TO
|IN_DONT_FOLLOW
|IN_ONLYDIR
);
2011 return log_error_errno(errno
, "Failed to watch journal directory: %m");
2013 /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
2017 /* OK, all preparatory steps done, let's wait until
2018 * inotify reports an event. */
2020 r
= fd_wait_for_event(watch_fd
, POLLIN
, USEC_INFINITY
);
2022 return log_error_errno(r
, "Failed to wait for event: %m");
2024 r
= flush_fd(watch_fd
);
2026 return log_error_errno(r
, "Failed to flush inotify events: %m");
2032 static int rotate(void) {
2033 return send_signal_and_wait(SIGUSR2
, "/run/systemd/journal/rotated");
2036 static int sync_journal(void) {
2037 return send_signal_and_wait(SIGRTMIN
+1, "/run/systemd/journal/synced");
2040 int main(int argc
, char *argv
[]) {
2042 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2043 bool need_seek
= false;
2044 sd_id128_t previous_boot_id
;
2045 bool previous_boot_id_valid
= false, first_line
= true;
2047 bool ellipsized
= false;
2049 setlocale(LC_ALL
, "");
2050 log_parse_environment();
2053 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2054 * split up into many files. */
2055 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2057 r
= parse_argv(argc
, argv
);
2061 signal(SIGWINCH
, columns_lines_cache_reset
);
2064 switch (arg_action
) {
2066 case ACTION_NEW_ID128
:
2067 r
= id128_print_new(true);
2070 case ACTION_SETUP_KEYS
:
2074 case ACTION_LIST_CATALOG
:
2075 case ACTION_DUMP_CATALOG
:
2076 case ACTION_UPDATE_CATALOG
: {
2077 _cleanup_free_
char *database
;
2079 database
= path_join(arg_root
, CATALOG_DATABASE
, NULL
);
2085 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2086 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2088 log_error_errno(r
, "Failed to list catalog: %m");
2090 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2092 (void) pager_open(arg_no_pager
, arg_pager_end
);
2095 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2097 r
= catalog_list(stdout
, database
, oneline
);
2099 log_error_errno(r
, "Failed to list catalog: %m");
2118 case ACTION_PRINT_HEADER
:
2120 case ACTION_DISK_USAGE
:
2121 case ACTION_LIST_BOOTS
:
2123 case ACTION_LIST_FIELDS
:
2124 case ACTION_LIST_FIELD_NAMES
:
2125 /* These ones require access to the journal files, continue below. */
2129 assert_not_reached("Unknown action");
2133 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2135 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2136 else if (arg_file_stdin
) {
2137 int ifd
= STDIN_FILENO
;
2138 r
= sd_journal_open_files_fd(&j
, &ifd
, 1, 0);
2139 } else if (arg_file
)
2140 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2141 else if (arg_machine
) {
2142 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2143 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2144 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2147 if (geteuid() != 0) {
2148 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2149 * the container, thus we need root privileges to override them. */
2150 log_error("Using the --machine= switch requires root privileges.");
2155 r
= sd_bus_open_system(&bus
);
2157 log_error_errno(r
, "Failed to open system bus: %m");
2161 r
= sd_bus_call_method(
2163 "org.freedesktop.machine1",
2164 "/org/freedesktop/machine1",
2165 "org.freedesktop.machine1.Manager",
2166 "OpenMachineRootDirectory",
2171 log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2175 r
= sd_bus_message_read(reply
, "h", &fd
);
2177 bus_log_parse_error(r
);
2181 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2183 r
= log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2187 r
= sd_journal_open_directory_fd(&j
, fd
, SD_JOURNAL_OS_ROOT
);
2191 r
= sd_journal_open(&j
, !arg_merge
*SD_JOURNAL_LOCAL_ONLY
+ arg_journal_type
);
2193 log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2197 r
= journal_access_check_and_warn(j
, arg_quiet
,
2198 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2202 switch (arg_action
) {
2204 case ACTION_NEW_ID128
:
2205 case ACTION_SETUP_KEYS
:
2206 case ACTION_LIST_CATALOG
:
2207 case ACTION_DUMP_CATALOG
:
2208 case ACTION_UPDATE_CATALOG
:
2212 assert_not_reached("Unexpected action.");
2214 case ACTION_PRINT_HEADER
:
2215 journal_print_header(j
);
2223 case ACTION_DISK_USAGE
: {
2225 char sbytes
[FORMAT_BYTES_MAX
];
2227 r
= sd_journal_get_usage(j
, &bytes
);
2231 printf("Archived and active journals take up %s in the file system.\n",
2232 format_bytes(sbytes
, sizeof(sbytes
), bytes
));
2236 case ACTION_LIST_BOOTS
:
2240 case ACTION_VACUUM
: {
2244 HASHMAP_FOREACH(d
, j
->directories_by_path
, i
) {
2250 q
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2252 log_error_errno(q
, "Failed to vacuum %s: %m", d
->path
);
2260 case ACTION_LIST_FIELD_NAMES
: {
2263 SD_JOURNAL_FOREACH_FIELD(j
, field
) {
2264 printf("%s\n", field
);
2273 case ACTION_LIST_FIELDS
:
2277 assert_not_reached("Unknown action");
2280 if (arg_boot_offset
!= 0 &&
2281 sd_journal_has_runtime_files(j
) > 0 &&
2282 sd_journal_has_persistent_files(j
) == 0) {
2283 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2287 /* add_boot() must be called first!
2288 * It may need to seek the journal to find parent boot IDs. */
2299 log_error_errno(r
, "Failed to add filter for units: %m");
2303 r
= add_syslog_identifier(j
);
2305 log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2309 r
= add_priorities(j
);
2313 r
= add_matches(j
, argv
+ optind
);
2317 if (DEBUG_LOGGING
) {
2318 _cleanup_free_
char *filter
;
2320 filter
= journal_make_match_string(j
);
2324 log_debug("Journal filter: %s", filter
);
2327 if (arg_action
== ACTION_LIST_FIELDS
) {
2333 r
= sd_journal_set_data_threshold(j
, 0);
2335 log_error_errno(r
, "Failed to unset data size threshold: %m");
2339 r
= sd_journal_query_unique(j
, arg_field
);
2341 log_error_errno(r
, "Failed to query unique data objects: %m");
2345 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2348 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2351 eq
= memchr(data
, '=', size
);
2353 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2355 printf("%.*s\n", (int) size
, (const char*) data
);
2364 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2366 r
= sd_journal_get_fd(j
);
2368 log_warning("Insufficent watch descriptors available. Reverting to -n.");
2370 } else if (r
== -EMEDIUMTYPE
) {
2371 log_error_errno(r
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2374 log_error_errno(r
, "Failed to get journal fd: %m");
2379 if (arg_cursor
|| arg_after_cursor
) {
2380 r
= sd_journal_seek_cursor(j
, arg_cursor
?: arg_after_cursor
);
2382 log_error_errno(r
, "Failed to seek to cursor: %m");
2387 r
= sd_journal_next_skip(j
, 1 + !!arg_after_cursor
);
2389 r
= sd_journal_previous_skip(j
, 1 + !!arg_after_cursor
);
2391 if (arg_after_cursor
&& r
< 2) {
2392 /* We couldn't find the next entry after the cursor. */
2399 } else if (arg_since_set
&& !arg_reverse
) {
2400 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2402 log_error_errno(r
, "Failed to seek to date: %m");
2405 r
= sd_journal_next(j
);
2407 } else if (arg_until_set
&& arg_reverse
) {
2408 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2410 log_error_errno(r
, "Failed to seek to date: %m");
2413 r
= sd_journal_previous(j
);
2415 } else if (arg_lines
>= 0) {
2416 r
= sd_journal_seek_tail(j
);
2418 log_error_errno(r
, "Failed to seek to tail: %m");
2422 r
= sd_journal_previous_skip(j
, arg_lines
);
2424 } else if (arg_reverse
) {
2425 r
= sd_journal_seek_tail(j
);
2427 log_error_errno(r
, "Failed to seek to tail: %m");
2431 r
= sd_journal_previous(j
);
2434 r
= sd_journal_seek_head(j
);
2436 log_error_errno(r
, "Failed to seek to head: %m");
2440 r
= sd_journal_next(j
);
2444 log_error_errno(r
, "Failed to iterate through journal: %m");
2451 (void) pager_open(arg_no_pager
, arg_pager_end
);
2453 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
)) {
2455 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2457 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2459 log_error_errno(r
, "Failed to get cutoff: %m");
2465 printf("-- Logs begin at %s. --\n",
2466 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2468 printf("-- Logs begin at %s, end at %s. --\n",
2469 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2470 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2475 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2477 size_t highlight
[2] = {};
2481 r
= sd_journal_next(j
);
2483 r
= sd_journal_previous(j
);
2485 log_error_errno(r
, "Failed to iterate through journal: %m");
2492 if (arg_until_set
&& !arg_reverse
) {
2495 r
= sd_journal_get_realtime_usec(j
, &usec
);
2497 log_error_errno(r
, "Failed to determine timestamp: %m");
2500 if (usec
> arg_until
)
2504 if (arg_since_set
&& arg_reverse
) {
2507 r
= sd_journal_get_realtime_usec(j
, &usec
);
2509 log_error_errno(r
, "Failed to determine timestamp: %m");
2512 if (usec
< arg_since
)
2516 if (!arg_merge
&& !arg_quiet
) {
2519 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2521 if (previous_boot_id_valid
&&
2522 !sd_id128_equal(boot_id
, previous_boot_id
))
2523 printf("%s-- Reboot --%s\n",
2524 ansi_highlight(), ansi_normal());
2526 previous_boot_id
= boot_id
;
2527 previous_boot_id_valid
= true;
2532 if (arg_compiled_pattern
) {
2533 _cleanup_(pcre2_match_data_freep
) pcre2_match_data
*md
= NULL
;
2534 const void *message
;
2538 md
= pcre2_match_data_create(1, NULL
);
2542 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2549 log_error_errno(r
, "Failed to get MESSAGE field: %m");
2553 assert_se(message
= startswith(message
, "MESSAGE="));
2555 r
= pcre2_match(arg_compiled_pattern
,
2557 len
- strlen("MESSAGE="),
2558 0, /* start at offset 0 in the subject */
2559 0, /* default options */
2562 if (r
== PCRE2_ERROR_NOMATCH
) {
2567 unsigned char buf
[LINE_MAX
];
2570 r2
= pcre2_get_error_message(r
, buf
, sizeof buf
);
2571 log_error("Pattern matching failed: %s",
2572 r2
< 0 ? "unknown error" : (char*) buf
);
2577 ovec
= pcre2_get_ovector_pointer(md
);
2578 highlight
[0] = ovec
[0];
2579 highlight
[1] = ovec
[1];
2584 arg_all
* OUTPUT_SHOW_ALL
|
2585 arg_full
* OUTPUT_FULL_WIDTH
|
2586 colors_enabled() * OUTPUT_COLOR
|
2587 arg_catalog
* OUTPUT_CATALOG
|
2588 arg_utc
* OUTPUT_UTC
|
2589 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2591 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2592 arg_output_fields
, highlight
, &ellipsized
);
2594 if (r
== -EADDRNOTAVAIL
)
2596 else if (r
< 0 || ferror(stdout
))
2601 /* If journalctl take a long time to process messages, and during that time journal file
2602 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2603 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2604 * in the "following" case. By periodically calling sd_journal_process() during the processing
2605 * loop we shrink the window of time a client instance has open file descriptors for rotated
2606 * (deleted) journal files. */
2607 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2608 r
= sd_journal_process(j
);
2610 log_error_errno(r
, "Failed to process inotify events: %m");
2617 if (n_shown
== 0 && !arg_quiet
)
2618 printf("-- No entries --\n");
2620 if (arg_show_cursor
) {
2621 _cleanup_free_
char *cursor
= NULL
;
2623 r
= sd_journal_get_cursor(j
, &cursor
);
2624 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2625 log_error_errno(r
, "Failed to get cursor: %m");
2627 printf("-- cursor: %s\n", cursor
);
2634 r
= sd_journal_wait(j
, (uint64_t) -1);
2636 log_error_errno(r
, "Couldn't wait for journal event: %m");
2647 strv_free(arg_file
);
2649 strv_free(arg_syslog_identifier
);
2650 strv_free(arg_system_units
);
2651 strv_free(arg_user_units
);
2652 strv_free(arg_output_fields
);
2655 free(arg_verify_key
);
2658 if (arg_compiled_pattern
)
2659 pcre2_code_free(arg_compiled_pattern
);
2662 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;