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 "stdio-util.h"
66 #include "syslog-util.h"
67 #include "terminal-util.h"
68 #include "tmpfile-util.h"
69 #include "unit-name.h"
70 #include "user-util.h"
73 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
74 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
77 /* Special values for arg_lines */
78 ARG_LINES_DEFAULT
= -2,
82 static OutputMode arg_output
= OUTPUT_SHORT
;
83 static bool arg_utc
= false;
84 static bool arg_follow
= false;
85 static bool arg_full
= true;
86 static bool arg_all
= false;
87 static PagerFlags arg_pager_flags
= 0;
88 static int arg_lines
= ARG_LINES_DEFAULT
;
89 static bool arg_no_tail
= false;
90 static bool arg_quiet
= false;
91 static bool arg_merge
= false;
92 static bool arg_boot
= false;
93 static sd_id128_t arg_boot_id
= {};
94 static int arg_boot_offset
= 0;
95 static bool arg_dmesg
= false;
96 static bool arg_no_hostname
= false;
97 static const char *arg_cursor
= NULL
;
98 static const char *arg_cursor_file
= NULL
;
99 static const char *arg_after_cursor
= NULL
;
100 static bool arg_show_cursor
= false;
101 static const char *arg_directory
= NULL
;
102 static char **arg_file
= NULL
;
103 static bool arg_file_stdin
= false;
104 static int arg_priorities
= 0xFF;
105 static Set
*arg_facilities
= NULL
;
106 static char *arg_verify_key
= NULL
;
108 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
109 static bool arg_force
= false;
111 static usec_t arg_since
, arg_until
;
112 static bool arg_since_set
= false, arg_until_set
= false;
113 static char **arg_syslog_identifier
= NULL
;
114 static char **arg_system_units
= NULL
;
115 static char **arg_user_units
= NULL
;
116 static const char *arg_field
= NULL
;
117 static bool arg_catalog
= false;
118 static bool arg_reverse
= false;
119 static int arg_journal_type
= 0;
120 static int arg_namespace_flags
= 0;
121 static char *arg_root
= NULL
;
122 static const char *arg_machine
= NULL
;
123 static const char *arg_namespace
= NULL
;
124 static uint64_t arg_vacuum_size
= 0;
125 static uint64_t arg_vacuum_n_files
= 0;
126 static usec_t arg_vacuum_time
= 0;
127 static char **arg_output_fields
= NULL
;
129 static const char *arg_pattern
= NULL
;
130 static pcre2_code
*arg_compiled_pattern
= NULL
;
131 static int arg_case_sensitive
= -1; /* -1 means be smart */
143 ACTION_UPDATE_CATALOG
,
146 ACTION_RELINQUISH_VAR
,
150 ACTION_ROTATE_AND_VACUUM
,
152 ACTION_LIST_FIELD_NAMES
,
153 } arg_action
= ACTION_SHOW
;
155 typedef struct BootId
{
159 LIST_FIELDS(struct BootId
, boot_list
);
163 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data
*, pcre2_match_data_free
);
164 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code
*, pcre2_code_free
);
166 static int pattern_compile(const char *pattern
, unsigned flags
, pcre2_code
**out
) {
168 PCRE2_SIZE erroroffset
;
171 p
= pcre2_compile((PCRE2_SPTR8
) pattern
,
172 PCRE2_ZERO_TERMINATED
, flags
, &errorcode
, &erroroffset
, NULL
);
174 unsigned char buf
[LINE_MAX
];
176 r
= pcre2_get_error_message(errorcode
, buf
, sizeof buf
);
178 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
179 "Bad pattern \"%s\": %s", pattern
,
180 r
< 0 ? "unknown error" : (char *)buf
);
189 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
190 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
198 if (!path_startswith(devpath
, "/dev/")) {
199 log_error("Devpath does not start with /dev/");
203 if (stat(devpath
, &st
) < 0)
204 return log_error_errno(errno
, "Couldn't stat file: %m");
206 r
= device_new_from_stat_rdev(&device
, &st
);
208 return log_error_errno(r
, "Failed to get device from devnum %u:%u: %m", major(st
.st_rdev
), minor(st
.st_rdev
));
210 for (d
= device
; d
; ) {
211 _cleanup_free_
char *match
= NULL
;
212 const char *subsys
, *sysname
, *devnode
;
215 r
= sd_device_get_subsystem(d
, &subsys
);
219 r
= sd_device_get_sysname(d
, &sysname
);
223 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
227 r
= sd_journal_add_match(j
, match
, 0);
229 return log_error_errno(r
, "Failed to add match: %m");
231 if (sd_device_get_devname(d
, &devnode
) >= 0) {
232 _cleanup_free_
char *match1
= NULL
;
234 r
= stat(devnode
, &st
);
236 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
238 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st
.st_mode
) ? 'b' : 'c', major(st
.st_rdev
), minor(st
.st_rdev
));
242 r
= sd_journal_add_match(j
, match1
, 0);
244 return log_error_errno(r
, "Failed to add match: %m");
248 if (sd_device_get_parent(d
, &parent
) < 0)
254 r
= add_match_this_boot(j
, arg_machine
);
256 return log_error_errno(r
, "Failed to add match for the current boot: %m");
261 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
264 return format_timestamp_utc(buf
, l
, t
);
266 return format_timestamp(buf
, l
, t
);
269 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
270 sd_id128_t id
= SD_ID128_NULL
;
273 if (streq(x
, "all")) {
274 *boot_id
= SD_ID128_NULL
;
277 } else if (strlen(x
) >= 32) {
281 r
= sd_id128_from_string(t
, &id
);
285 if (!IN_SET(*x
, 0, '-', '+'))
289 r
= safe_atoi(x
, &off
);
294 r
= safe_atoi(x
, &off
);
308 static int help_facilities(void) {
310 puts("Available facilities:");
312 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
313 _cleanup_free_
char *t
= NULL
;
315 if (log_facility_unshifted_to_string_alloc(i
, &t
))
323 static int help(void) {
324 _cleanup_free_
char *link
= NULL
;
327 (void) pager_open(arg_pager_flags
);
329 r
= terminal_urlify_man("journalctl", "1", &link
);
333 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
334 "%5$sQuery the journal.%6$s\n\n"
336 " --system Show the system journal\n"
337 " --user Show the user journal for the current user\n"
338 " -M --machine=CONTAINER Operate on local container\n"
339 " -S --since=DATE Show entries not older than the specified date\n"
340 " -U --until=DATE Show entries not newer than the specified date\n"
341 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
342 " --after-cursor=CURSOR Show entries after the specified cursor\n"
343 " --show-cursor Print the cursor after all the entries\n"
344 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
345 " -b --boot[=ID] Show current boot or the specified boot\n"
346 " --list-boots Show terse information about recorded boots\n"
347 " -k --dmesg Show kernel message log from the current boot\n"
348 " -u --unit=UNIT Show logs from the specified unit\n"
349 " --user-unit=UNIT Show logs from the specified user unit\n"
350 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
351 " -p --priority=RANGE Show entries with the specified priority\n"
352 " --facility=FACILITY... Show entries with the specified facilities\n"
353 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
354 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
355 " -e --pager-end Immediately jump to the end in the pager\n"
356 " -f --follow Follow the journal\n"
357 " -n --lines[=INTEGER] Number of journal entries to show\n"
358 " --no-tail Show all lines, even in follow mode\n"
359 " -r --reverse Show the newest entries first\n"
360 " -o --output=STRING Change journal output mode (short, short-precise,\n"
361 " short-iso, short-iso-precise, short-full,\n"
362 " short-monotonic, short-unix, verbose, export,\n"
363 " json, json-pretty, json-sse, json-seq, cat,\n"
365 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
366 " --utc Express time in Coordinated Universal Time (UTC)\n"
367 " -x --catalog Add message explanations where available\n"
368 " --no-full Ellipsize fields\n"
369 " -a --all Show all fields, including long and unprintable\n"
370 " -q --quiet Do not show info messages and privilege warning\n"
371 " --no-pager Do not pipe output into a pager\n"
372 " --no-hostname Suppress output of hostname field\n"
373 " -m --merge Show entries from all available journals\n"
374 " -D --directory=PATH Show journal files from directory\n"
375 " --file=PATH Show journal file\n"
376 " --root=ROOT Operate on files below a root directory\n"
377 " --namespace=NAMESPACE Show journal data from specified namespace\n"
378 " --interval=TIME Time interval for changing the FSS sealing key\n"
379 " --verify-key=KEY Specify FSS verification key\n"
380 " --force Override of the FSS key pair with --setup-keys\n"
381 "\n%3$sCommands:%4$s\n"
382 " -h --help Show this help text\n"
383 " --version Show package version\n"
384 " -N --fields List all field names currently used\n"
385 " -F --field=FIELD List all values that a specified field takes\n"
386 " --disk-usage Show total disk usage of all journal files\n"
387 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
388 " --vacuum-files=INT Leave only the specified number of journal files\n"
389 " --vacuum-time=TIME Remove journal files older than specified time\n"
390 " --verify Verify journal file consistency\n"
391 " --sync Synchronize unwritten journal messages to disk\n"
392 " --relinquish-var Stop logging to disk, log to temporary file system\n"
393 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
394 " --flush Flush all journal data from /run into /var\n"
395 " --rotate Request immediate rotation of the journal files\n"
396 " --header Show journal header information\n"
397 " --list-catalog Show all message IDs in the catalog\n"
398 " --dump-catalog Show entries in the message catalog\n"
399 " --update-catalog Update the message catalog database\n"
400 " --setup-keys Generate a new FSS key pair\n"
401 "\nSee the %2$s for details.\n"
402 , program_invocation_short_name
404 , ansi_underline(), ansi_normal()
405 , ansi_highlight(), ansi_normal()
411 static int parse_argv(int argc
, char *argv
[]) {
445 ARG_SMART_RELINQUISH_VAR
,
455 static const struct option options
[] = {
456 { "help", no_argument
, NULL
, 'h' },
457 { "version" , no_argument
, NULL
, ARG_VERSION
},
458 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
459 { "pager-end", no_argument
, NULL
, 'e' },
460 { "follow", no_argument
, NULL
, 'f' },
461 { "force", no_argument
, NULL
, ARG_FORCE
},
462 { "output", required_argument
, NULL
, 'o' },
463 { "all", no_argument
, NULL
, 'a' },
464 { "full", no_argument
, NULL
, 'l' },
465 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
466 { "lines", optional_argument
, NULL
, 'n' },
467 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
468 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
469 { "quiet", no_argument
, NULL
, 'q' },
470 { "merge", no_argument
, NULL
, 'm' },
471 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
472 { "boot", optional_argument
, NULL
, 'b' },
473 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
474 { "dmesg", no_argument
, NULL
, 'k' },
475 { "system", no_argument
, NULL
, ARG_SYSTEM
},
476 { "user", no_argument
, NULL
, ARG_USER
},
477 { "directory", required_argument
, NULL
, 'D' },
478 { "file", required_argument
, NULL
, ARG_FILE
},
479 { "root", required_argument
, NULL
, ARG_ROOT
},
480 { "header", no_argument
, NULL
, ARG_HEADER
},
481 { "identifier", required_argument
, NULL
, 't' },
482 { "priority", required_argument
, NULL
, 'p' },
483 { "facility", required_argument
, NULL
, ARG_FACILITY
},
484 { "grep", required_argument
, NULL
, 'g' },
485 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
486 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
487 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
488 { "verify", no_argument
, NULL
, ARG_VERIFY
},
489 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
490 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
491 { "cursor", required_argument
, NULL
, 'c' },
492 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
493 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
494 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
495 { "since", required_argument
, NULL
, 'S' },
496 { "until", required_argument
, NULL
, 'U' },
497 { "unit", required_argument
, NULL
, 'u' },
498 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
499 { "field", required_argument
, NULL
, 'F' },
500 { "fields", no_argument
, NULL
, 'N' },
501 { "catalog", no_argument
, NULL
, 'x' },
502 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
503 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
504 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
505 { "reverse", no_argument
, NULL
, 'r' },
506 { "machine", required_argument
, NULL
, 'M' },
507 { "utc", no_argument
, NULL
, ARG_UTC
},
508 { "flush", no_argument
, NULL
, ARG_FLUSH
},
509 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
510 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
511 { "sync", no_argument
, NULL
, ARG_SYNC
},
512 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
513 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
514 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
515 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
516 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
517 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
518 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
527 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
538 arg_pager_flags
|= PAGER_DISABLE
;
542 arg_pager_flags
|= PAGER_JUMP_TO_END
;
544 if (arg_lines
== ARG_LINES_DEFAULT
)
554 if (streq(optarg
, "help")) {
555 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
559 arg_output
= output_mode_from_string(optarg
);
561 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown output format '%s'.", optarg
);
563 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
582 if (streq(optarg
, "all"))
583 arg_lines
= ARG_LINES_ALL
;
585 r
= safe_atoi(optarg
, &arg_lines
);
586 if (r
< 0 || arg_lines
< 0)
587 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
592 /* Hmm, no argument? Maybe the next
593 * word on the command line is
594 * supposed to be the argument? Let's
595 * see if there is one, and is
599 if (streq(argv
[optind
], "all")) {
600 arg_lines
= ARG_LINES_ALL
;
602 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
616 arg_action
= ACTION_NEW_ID128
;
629 arg_boot_id
= SD_ID128_NULL
;
635 arg_boot_id
= SD_ID128_NULL
;
639 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
641 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
645 /* Hmm, no argument? Maybe the next
646 * word on the command line is
647 * supposed to be the argument? Let's
648 * see if there is one and is parsable
649 * as a boot descriptor... */
650 } else if (optind
< argc
) {
651 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
660 arg_action
= ACTION_LIST_BOOTS
;
664 arg_boot
= arg_dmesg
= true;
668 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
672 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
676 arg_machine
= optarg
;
680 if (streq(optarg
, "*")) {
681 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
682 arg_namespace
= NULL
;
683 } else if (startswith(optarg
, "+")) {
684 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
685 arg_namespace
= optarg
+ 1;
686 } else if (isempty(optarg
)) {
687 arg_namespace_flags
= 0;
688 arg_namespace
= NULL
;
690 arg_namespace_flags
= 0;
691 arg_namespace
= optarg
;
697 arg_directory
= optarg
;
701 if (streq(optarg
, "-"))
702 /* An undocumented feature: we can read journal files from STDIN. We don't document
703 * this though, since after all we only support this for mmap-able, seekable files, and
704 * not for example pipes which are probably the primary usecase for reading things from
705 * STDIN. To avoid confusion we hence don't document this feature. */
706 arg_file_stdin
= true;
708 r
= glob_extend(&arg_file
, optarg
);
710 return log_error_errno(r
, "Failed to add paths: %m");
715 r
= parse_path_argument_and_warn(optarg
, true, &arg_root
);
724 case ARG_CURSOR_FILE
:
725 arg_cursor_file
= optarg
;
728 case ARG_AFTER_CURSOR
:
729 arg_after_cursor
= optarg
;
732 case ARG_SHOW_CURSOR
:
733 arg_show_cursor
= true;
737 arg_action
= ACTION_PRINT_HEADER
;
741 arg_action
= ACTION_VERIFY
;
745 arg_action
= ACTION_DISK_USAGE
;
748 case ARG_VACUUM_SIZE
:
749 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
751 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
753 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
756 case ARG_VACUUM_FILES
:
757 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
759 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
761 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
764 case ARG_VACUUM_TIME
:
765 r
= parse_sec(optarg
, &arg_vacuum_time
);
767 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
769 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
778 arg_action
= ACTION_SETUP_KEYS
;
782 r
= free_and_strdup(&arg_verify_key
, optarg
);
785 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
786 * in ps or htop output. */
787 memset(optarg
, 'x', strlen(optarg
));
789 arg_action
= ACTION_VERIFY
;
794 r
= parse_sec(optarg
, &arg_interval
);
795 if (r
< 0 || arg_interval
<= 0)
796 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
797 "Failed to parse sealing key change interval: %s", optarg
);
804 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
805 "Compiled without forward-secure sealing support.");
811 dots
= strstr(optarg
, "..");
813 _cleanup_free_
char *a
= NULL
;
817 a
= strndup(optarg
, dots
- optarg
);
821 from
= log_level_from_string(a
);
822 to
= log_level_from_string(dots
+ 2);
824 if (from
< 0 || to
< 0)
825 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
826 "Failed to parse log level range %s", optarg
);
831 for (i
= from
; i
<= to
; i
++)
832 arg_priorities
|= 1 << i
;
834 for (i
= to
; i
<= from
; i
++)
835 arg_priorities
|= 1 << i
;
841 p
= log_level_from_string(optarg
);
843 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
844 "Unknown log level %s", optarg
);
848 for (i
= 0; i
<= p
; i
++)
849 arg_priorities
|= 1 << i
;
859 _cleanup_free_
char *fac
= NULL
;
862 r
= extract_first_word(&p
, &fac
, ",", 0);
864 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
868 if (streq(fac
, "help")) {
873 num
= log_facility_unshifted_from_string(fac
);
875 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
876 "Bad --facility= argument \"%s\".", fac
);
878 r
= set_ensure_allocated(&arg_facilities
, NULL
);
882 r
= set_put(arg_facilities
, INT_TO_PTR(num
));
892 arg_pattern
= optarg
;
895 case ARG_CASE_SENSITIVE
:
897 r
= parse_boolean(optarg
);
899 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
900 arg_case_sensitive
= r
;
902 arg_case_sensitive
= true;
907 case ARG_CASE_SENSITIVE
:
908 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Compiled without pattern matching support");
912 r
= parse_timestamp(optarg
, &arg_since
);
914 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
915 "Failed to parse timestamp: %s", optarg
);
916 arg_since_set
= true;
920 r
= parse_timestamp(optarg
, &arg_until
);
922 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
923 "Failed to parse timestamp: %s", optarg
);
924 arg_until_set
= true;
928 r
= strv_extend(&arg_syslog_identifier
, optarg
);
934 r
= strv_extend(&arg_system_units
, optarg
);
940 r
= strv_extend(&arg_user_units
, optarg
);
946 arg_action
= ACTION_LIST_FIELDS
;
951 arg_action
= ACTION_LIST_FIELD_NAMES
;
954 case ARG_NO_HOSTNAME
:
955 arg_no_hostname
= true;
962 case ARG_LIST_CATALOG
:
963 arg_action
= ACTION_LIST_CATALOG
;
966 case ARG_DUMP_CATALOG
:
967 arg_action
= ACTION_DUMP_CATALOG
;
970 case ARG_UPDATE_CATALOG
:
971 arg_action
= ACTION_UPDATE_CATALOG
;
983 arg_action
= ACTION_FLUSH
;
986 case ARG_SMART_RELINQUISH_VAR
: {
987 int root_mnt_id
, log_mnt_id
;
989 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
990 * if it's on the same mount as the root file system there's no point in
991 * relinquishing access and we can leave journald write to it until the very last
994 r
= path_get_mnt_id("/", &root_mnt_id
);
996 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
998 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1000 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1001 else if (root_mnt_id
== log_mnt_id
) {
1002 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1005 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1011 case ARG_RELINQUISH_VAR
:
1012 arg_action
= ACTION_RELINQUISH_VAR
;
1016 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1020 arg_action
= ACTION_SYNC
;
1023 case ARG_OUTPUT_FIELDS
: {
1024 _cleanup_strv_free_
char **v
= NULL
;
1026 v
= strv_split(optarg
, ",");
1030 if (!arg_output_fields
)
1031 arg_output_fields
= TAKE_PTR(v
);
1033 r
= strv_extend_strv(&arg_output_fields
, v
, true);
1044 assert_not_reached("Unhandled option");
1047 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
1050 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
> 1) {
1051 log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root.");
1055 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
) {
1056 log_error("--since= must be before --until=.");
1060 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1) {
1061 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
1065 if (arg_follow
&& arg_reverse
) {
1066 log_error("Please specify either --reverse= or --follow=, not both.");
1070 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
) {
1071 log_error("Extraneous arguments starting with '%s'", argv
[optind
]);
1075 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
) {
1076 log_error("Using --boot or --list-boots with --merge is not supported.");
1080 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1081 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1082 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1083 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1084 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1088 arg_system_units
= strv_free(arg_system_units
);
1095 if (arg_case_sensitive
>= 0)
1096 flags
= !arg_case_sensitive
* PCRE2_CASELESS
;
1098 _cleanup_(pcre2_match_data_freep
) pcre2_match_data
*md
= NULL
;
1100 _cleanup_(pcre2_code_freep
) pcre2_code
*cs
= NULL
;
1102 md
= pcre2_match_data_create(1, NULL
);
1106 r
= pattern_compile("[[:upper:]]", 0, &cs
);
1110 r
= pcre2_match(cs
, (PCRE2_SPTR8
) arg_pattern
, PCRE2_ZERO_TERMINATED
, 0, 0, md
, NULL
);
1113 flags
= !has_case
* PCRE2_CASELESS
;
1116 log_debug("Doing case %s matching based on %s",
1117 flags
& PCRE2_CASELESS
? "insensitive" : "sensitive",
1118 arg_case_sensitive
>= 0 ? "request" : "pattern casing");
1120 r
= pattern_compile(arg_pattern
, flags
, &arg_compiled_pattern
);
1129 static int add_matches(sd_journal
*j
, char **args
) {
1131 bool have_term
= false;
1135 STRV_FOREACH(i
, args
) {
1138 if (streq(*i
, "+")) {
1141 r
= sd_journal_add_disjunction(j
);
1144 } else if (path_is_absolute(*i
)) {
1145 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1148 r
= chase_symlinks(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1150 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1152 if (lstat(p
, &st
) < 0)
1153 return log_error_errno(errno
, "Couldn't stat file: %m");
1155 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1156 if (executable_is_script(p
, &interpreter
) > 0) {
1157 _cleanup_free_
char *comm
;
1159 comm
= strndup(basename(p
), 15);
1163 t
= strjoin("_COMM=", comm
);
1167 /* Append _EXE only if the interpreter is not a link.
1168 Otherwise, it might be outdated often. */
1169 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1170 t2
= strjoin("_EXE=", interpreter
);
1175 t
= strjoin("_EXE=", p
);
1180 r
= sd_journal_add_match(j
, t
, 0);
1183 r
= sd_journal_add_match(j
, t2
, 0);
1185 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1186 r
= add_matches_for_device(j
, p
);
1190 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1191 "File is neither a device node, nor regular file, nor executable: %s",
1196 r
= sd_journal_add_match(j
, *i
, 0);
1201 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1204 if (!strv_isempty(args
) && !have_term
)
1205 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1206 "\"+\" can only be used between terms");
1211 static void boot_id_free_all(BootId
*l
) {
1215 LIST_REMOVE(boot_list
, l
, i
);
1220 static int discover_next_boot(sd_journal
*j
,
1221 sd_id128_t previous_boot_id
,
1225 _cleanup_free_ BootId
*next_boot
= NULL
;
1226 char match
[9+32+1] = "_BOOT_ID=";
1233 /* We expect the journal to be on the last position of a boot
1234 * (in relation to the direction we are going), so that the next
1235 * invocation of sd_journal_next/previous will be from a different
1236 * boot. We then collect any information we desire and then jump
1237 * to the last location of the new boot by using a _BOOT_ID match
1238 * coming from the other journal direction. */
1240 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1241 * we can actually advance to a *different* boot. */
1242 sd_journal_flush_matches(j
);
1246 r
= sd_journal_previous(j
);
1248 r
= sd_journal_next(j
);
1252 return 0; /* End of journal, yay. */
1254 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1258 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1259 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1260 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1261 * complete than the main entry array, and hence might reference an entry that's not actually the last
1262 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1263 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1266 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1268 next_boot
= new0(BootId
, 1);
1272 next_boot
->id
= boot_id
;
1274 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1278 /* Now seek to the last occurrence of this boot ID. */
1279 sd_id128_to_string(next_boot
->id
, match
+ 9);
1280 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1285 r
= sd_journal_seek_head(j
);
1287 r
= sd_journal_seek_tail(j
);
1292 r
= sd_journal_next(j
);
1294 r
= sd_journal_previous(j
);
1298 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1299 "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. */
1301 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1305 *ret
= TAKE_PTR(next_boot
);
1310 static int get_boots(
1313 sd_id128_t
*boot_id
,
1318 BootId
*head
= NULL
, *tail
= NULL
, *id
;
1319 const bool advance_older
= boot_id
&& offset
<= 0;
1320 sd_id128_t previous_boot_id
;
1324 /* Adjust for the asymmetry that offset 0 is
1325 * the last (and current) boot, while 1 is considered the
1326 * (chronological) first boot in the journal. */
1327 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1329 /* Advance to the earliest/latest occurrence of our reference
1330 * boot ID (taking our lookup direction into account), so that
1331 * discover_next_boot() can do its job.
1332 * If no reference is given, the journal head/tail will do,
1333 * they're "virtual" boots after all. */
1334 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1335 char match
[9+32+1] = "_BOOT_ID=";
1337 sd_journal_flush_matches(j
);
1339 sd_id128_to_string(*boot_id
, match
+ 9);
1340 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1345 r
= sd_journal_seek_head(j
); /* seek to oldest */
1347 r
= sd_journal_seek_tail(j
); /* seek to newest */
1352 r
= sd_journal_next(j
); /* read the oldest entry */
1354 r
= sd_journal_previous(j
); /* read the most recently added entry */
1359 else if (offset
== 0) {
1364 /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot
1365 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1366 * the following entry, which must then have an older/newer boot ID */
1370 r
= sd_journal_seek_tail(j
); /* seek to newest */
1372 r
= sd_journal_seek_head(j
); /* seek to oldest */
1376 /* No sd_journal_next()/_previous() here.
1378 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1379 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1383 previous_boot_id
= SD_ID128_NULL
;
1385 _cleanup_free_ BootId
*current
= NULL
;
1387 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1389 boot_id_free_all(head
);
1396 previous_boot_id
= current
->id
;
1400 offset
+= advance_older
? 1 : -1;
1405 *boot_id
= current
->id
;
1409 LIST_FOREACH(boot_list
, id
, head
) {
1410 if (sd_id128_equal(id
->id
, current
->id
)) {
1411 /* boot id already stored, something wrong with the journal files */
1412 /* exiting as otherwise this problem would cause forever loop */
1416 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1417 tail
= TAKE_PTR(current
);
1426 sd_journal_flush_matches(j
);
1431 static int list_boots(sd_journal
*j
) {
1433 BootId
*id
, *all_ids
;
1437 count
= get_boots(j
, &all_ids
, NULL
, 0);
1439 return log_error_errno(count
, "Failed to determine boots: %m");
1443 (void) pager_open(arg_pager_flags
);
1445 /* numbers are one less, but we need an extra char for the sign */
1446 w
= DECIMAL_STR_WIDTH(count
- 1) + 1;
1449 LIST_FOREACH(boot_list
, id
, all_ids
) {
1450 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1452 printf("% *i " SD_ID128_FORMAT_STR
" %s—%s\n",
1454 SD_ID128_FORMAT_VAL(id
->id
),
1455 format_timestamp_maybe_utc(a
, sizeof(a
), id
->first
),
1456 format_timestamp_maybe_utc(b
, sizeof(b
), id
->last
));
1460 boot_id_free_all(all_ids
);
1465 static int add_boot(sd_journal
*j
) {
1466 char match
[9+32+1] = "_BOOT_ID=";
1475 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1476 * We can do this only when we logs are coming from the current machine,
1477 * so take the slow path if log location is specified. */
1478 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1479 !arg_directory
&& !arg_file
&& !arg_root
)
1480 return add_match_this_boot(j
, arg_machine
);
1482 boot_id
= arg_boot_id
;
1483 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1486 const char *reason
= (r
== 0) ? "No such boot ID in journal" : strerror_safe(r
);
1488 if (sd_id128_is_null(arg_boot_id
))
1489 log_error("Data from the specified boot (%+i) is not available: %s",
1490 arg_boot_offset
, reason
);
1492 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1493 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1495 return r
== 0 ? -ENODATA
: r
;
1498 sd_id128_to_string(boot_id
, match
+ 9);
1500 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1502 return log_error_errno(r
, "Failed to add match: %m");
1504 r
= sd_journal_add_conjunction(j
);
1506 return log_error_errno(r
, "Failed to add conjunction: %m");
1511 static int add_dmesg(sd_journal
*j
) {
1518 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1519 STRLEN("_TRANSPORT=kernel"));
1521 return log_error_errno(r
, "Failed to add match: %m");
1523 r
= sd_journal_add_conjunction(j
);
1525 return log_error_errno(r
, "Failed to add conjunction: %m");
1530 static int get_possible_units(
1536 _cleanup_set_free_free_ Set
*found
;
1540 found
= set_new(&string_hash_ops
);
1544 NULSTR_FOREACH(field
, fields
) {
1548 r
= sd_journal_query_unique(j
, field
);
1552 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1553 char **pattern
, *eq
;
1555 _cleanup_free_
char *u
= NULL
;
1557 eq
= memchr(data
, '=', size
);
1559 prefix
= eq
- (char*) data
+ 1;
1563 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1567 STRV_FOREACH(pattern
, patterns
)
1568 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1569 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1571 r
= set_consume(found
, u
);
1573 if (r
< 0 && r
!= -EEXIST
)
1581 *units
= TAKE_PTR(found
);
1586 /* This list is supposed to return the superset of unit names
1587 * possibly matched by rules added with add_matches_for_unit... */
1588 #define SYSTEM_UNITS \
1592 "OBJECT_SYSTEMD_UNIT\0" \
1595 /* ... and add_matches_for_user_unit */
1596 #define USER_UNITS \
1597 "_SYSTEMD_USER_UNIT\0" \
1599 "COREDUMP_USER_UNIT\0" \
1600 "OBJECT_SYSTEMD_USER_UNIT\0" \
1601 "_SYSTEMD_USER_SLICE\0"
1603 static int add_units(sd_journal
*j
) {
1604 _cleanup_strv_free_
char **patterns
= NULL
;
1610 STRV_FOREACH(i
, arg_system_units
) {
1611 _cleanup_free_
char *u
= NULL
;
1613 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1617 if (string_is_glob(u
)) {
1618 r
= strv_push(&patterns
, u
);
1623 r
= add_matches_for_unit(j
, u
);
1626 r
= sd_journal_add_disjunction(j
);
1633 if (!strv_isempty(patterns
)) {
1634 _cleanup_set_free_free_ Set
*units
= NULL
;
1638 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1642 SET_FOREACH(u
, units
, it
) {
1643 r
= add_matches_for_unit(j
, u
);
1646 r
= sd_journal_add_disjunction(j
);
1653 patterns
= strv_free(patterns
);
1655 STRV_FOREACH(i
, arg_user_units
) {
1656 _cleanup_free_
char *u
= NULL
;
1658 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1662 if (string_is_glob(u
)) {
1663 r
= strv_push(&patterns
, u
);
1668 r
= add_matches_for_user_unit(j
, u
, getuid());
1671 r
= sd_journal_add_disjunction(j
);
1678 if (!strv_isempty(patterns
)) {
1679 _cleanup_set_free_free_ Set
*units
= NULL
;
1683 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1687 SET_FOREACH(u
, units
, it
) {
1688 r
= add_matches_for_user_unit(j
, u
, getuid());
1691 r
= sd_journal_add_disjunction(j
);
1698 /* Complain if the user request matches but nothing whatsoever was
1699 * found, since otherwise everything would be matched. */
1700 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1703 r
= sd_journal_add_conjunction(j
);
1710 static int add_priorities(sd_journal
*j
) {
1711 char match
[] = "PRIORITY=0";
1715 if (arg_priorities
== 0xFF)
1718 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1719 if (arg_priorities
& (1 << i
)) {
1720 match
[sizeof(match
)-2] = '0' + i
;
1722 r
= sd_journal_add_match(j
, match
, strlen(match
));
1724 return log_error_errno(r
, "Failed to add match: %m");
1727 r
= sd_journal_add_conjunction(j
);
1729 return log_error_errno(r
, "Failed to add conjunction: %m");
1734 static int add_facilities(sd_journal
*j
) {
1739 SET_FOREACH(p
, arg_facilities
, it
) {
1740 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1742 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1744 r
= sd_journal_add_match(j
, match
, strlen(match
));
1746 return log_error_errno(r
, "Failed to add match: %m");
1752 static int add_syslog_identifier(sd_journal
*j
) {
1758 STRV_FOREACH(i
, arg_syslog_identifier
) {
1759 _cleanup_free_
char *u
= NULL
;
1761 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1764 r
= sd_journal_add_match(j
, u
, 0);
1767 r
= sd_journal_add_disjunction(j
);
1772 r
= sd_journal_add_conjunction(j
);
1779 static int setup_keys(void) {
1781 size_t mpk_size
, seed_size
, state_size
, i
;
1782 uint8_t *mpk
, *seed
, *state
;
1784 sd_id128_t machine
, boot
;
1785 char *p
= NULL
, *k
= NULL
;
1789 r
= stat("/var/log/journal", &st
);
1790 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1791 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1793 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1794 log_error("%s is not a directory, must be using persistent logging for FSS.",
1795 "/var/log/journal");
1796 return r
< 0 ? -errno
: -ENOTDIR
;
1799 r
= sd_id128_get_machine(&machine
);
1801 return log_error_errno(r
, "Failed to get machine ID: %m");
1803 r
= sd_id128_get_boot(&boot
);
1805 return log_error_errno(r
, "Failed to get boot ID: %m");
1807 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1808 SD_ID128_FORMAT_VAL(machine
)) < 0)
1813 if (r
< 0 && errno
!= ENOENT
) {
1814 r
= log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1817 } else if (access(p
, F_OK
) >= 0) {
1818 log_error("Sealing key file %s exists already. Use --force to recreate.", p
);
1823 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1824 SD_ID128_FORMAT_VAL(machine
)) < 0) {
1829 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1830 mpk
= alloca(mpk_size
);
1832 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1833 seed
= alloca(seed_size
);
1835 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1836 state
= alloca(state_size
);
1838 fd
= open("/dev/random", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1840 r
= log_error_errno(errno
, "Failed to open /dev/random: %m");
1844 log_info("Generating seed...");
1845 r
= loop_read_exact(fd
, seed
, seed_size
, true);
1847 log_error_errno(r
, "Failed to read random seed: %m");
1851 log_info("Generating key pair...");
1852 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1854 log_info("Generating sealing key...");
1855 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1857 assert(arg_interval
> 0);
1859 n
= now(CLOCK_REALTIME
);
1863 fd
= mkostemp_safe(k
);
1865 r
= log_error_errno(fd
, "Failed to open %s: %m", k
);
1869 /* Enable secure remove, exclusion from dump, synchronous
1870 * writing and in-place updating */
1871 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
);
1873 log_warning_errno(r
, "Failed to set file attributes: %m");
1875 struct FSSHeader h
= {
1876 .machine_id
= machine
,
1878 .header_size
= htole64(sizeof(h
)),
1879 .start_usec
= htole64(n
* arg_interval
),
1880 .interval_usec
= htole64(arg_interval
),
1881 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1882 .fsprg_state_size
= htole64(state_size
),
1885 memcpy(h
.signature
, "KSHHRHLP", 8);
1887 r
= loop_write(fd
, &h
, sizeof(h
), false);
1889 log_error_errno(r
, "Failed to write header: %m");
1893 r
= loop_write(fd
, state
, state_size
, false);
1895 log_error_errno(r
, "Failed to write state: %m");
1899 if (link(k
, p
) < 0) {
1900 r
= log_error_errno(errno
, "Failed to link file: %m");
1907 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1908 "the following local file. This key file is automatically updated when the\n"
1909 "sealing key is advanced. It should not be used on multiple hosts.\n"
1913 "Please write down the following %ssecret verification key%s. It should be stored\n"
1914 "at a safe location and should not be saved locally on disk.\n"
1916 ansi_highlight(), ansi_normal(),
1918 ansi_highlight(), ansi_normal(),
1919 ansi_highlight_red());
1922 for (i
= 0; i
< seed_size
; i
++) {
1923 if (i
> 0 && i
% 3 == 0)
1925 printf("%02x", ((uint8_t*) seed
)[i
]);
1928 printf("/%llx-%llx\n", (unsigned long long) n
, (unsigned long long) arg_interval
);
1931 char tsb
[FORMAT_TIMESPAN_MAX
], *hn
;
1935 "The sealing key is automatically changed every %s.\n",
1937 format_timespan(tsb
, sizeof(tsb
), arg_interval
, 0));
1939 hn
= gethostname_malloc();
1942 hostname_cleanup(hn
);
1943 fprintf(stderr
, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR
".\n", hn
, SD_ID128_FORMAT_VAL(machine
));
1945 fprintf(stderr
, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR
".\n", SD_ID128_FORMAT_VAL(machine
));
1948 /* If this is not an UTF-8 system don't print any QR codes */
1949 if (is_locale_utf8()) {
1950 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr
);
1951 print_qr_code(stderr
, seed
, seed_size
, n
, arg_interval
, hn
, machine
);
1971 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1972 "Forward-secure sealing not available.");
1976 static int verify(sd_journal
*j
) {
1983 log_show_color(true);
1985 ORDERED_HASHMAP_FOREACH(f
, j
->files
, i
) {
1987 usec_t first
= 0, validated
= 0, last
= 0;
1990 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1991 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1994 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, true);
1996 /* If the key was invalid give up right-away. */
1999 log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
2002 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
], c
[FORMAT_TIMESPAN_MAX
];
2003 log_info("PASS: %s", f
->path
);
2005 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
2006 if (validated
> 0) {
2007 log_info("=> Validated from %s to %s, final %s entries not sealed.",
2008 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
2009 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
2010 format_timespan(c
, sizeof(c
), last
> validated
? last
- validated
: 0, 0));
2011 } else if (last
> 0)
2012 log_info("=> No sealing yet, %s of entries not sealed.",
2013 format_timespan(c
, sizeof(c
), last
- first
, 0));
2015 log_info("=> No sealing yet, no entries in file.");
2023 static int simple_varlink_call(const char *option
, const char *method
) {
2024 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2025 const char *error
, *fn
;
2029 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2031 fn
= arg_namespace
?
2032 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2033 "/run/systemd/journal/io.systemd.journal";
2035 r
= varlink_connect_address(&link
, fn
);
2037 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2039 (void) varlink_set_description(link
, "journal");
2040 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2042 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2044 return log_error_errno(r
, "Failed to execute varlink call: %m");
2046 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2047 "Failed to execute varlink call: %s", error
);
2052 static int flush_to_var(void) {
2053 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2056 static int relinquish_var(void) {
2057 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2060 static int rotate(void) {
2061 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2064 static int sync_journal(void) {
2065 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2068 static int wait_for_change(sd_journal
*j
, int poll_fd
) {
2069 struct pollfd pollfds
[] = {
2070 { .fd
= poll_fd
, .events
= POLLIN
},
2071 { .fd
= STDOUT_FILENO
},
2079 assert(poll_fd
>= 0);
2081 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
2082 * i.e. when it is closed. */
2084 r
= sd_journal_get_timeout(j
, &timeout
);
2086 return log_error_errno(r
, "Failed to determine journal waiting time: %m");
2088 if (ppoll(pollfds
, ELEMENTSOF(pollfds
),
2089 timeout
== USEC_INFINITY
? NULL
: timespec_store(&ts
, timeout
), NULL
) < 0) {
2093 return log_error_errno(errno
, "Couldn't wait for journal event: %m");
2096 if (pollfds
[1].revents
& (POLLHUP
|POLLERR
)) /* STDOUT has been closed? */
2097 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
),
2098 "Standard output has been closed.");
2100 r
= sd_journal_process(j
);
2102 return log_error_errno(r
, "Failed to process journal events: %m");
2107 int main(int argc
, char *argv
[]) {
2108 bool previous_boot_id_valid
= false, first_line
= true, ellipsized
= false, need_seek
= false;
2109 bool use_cursor
= false, after_cursor
= false;
2110 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2111 sd_id128_t previous_boot_id
;
2112 int n_shown
= 0, r
, poll_fd
= -1;
2114 setlocale(LC_ALL
, "");
2115 log_show_color(true);
2116 log_parse_environment();
2119 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2120 * split up into many files. */
2121 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2123 r
= parse_argv(argc
, argv
);
2127 signal(SIGWINCH
, columns_lines_cache_reset
);
2130 switch (arg_action
) {
2132 case ACTION_NEW_ID128
:
2133 r
= id128_print_new(ID128_PRINT_PRETTY
);
2136 case ACTION_SETUP_KEYS
:
2140 case ACTION_LIST_CATALOG
:
2141 case ACTION_DUMP_CATALOG
:
2142 case ACTION_UPDATE_CATALOG
: {
2143 _cleanup_free_
char *database
;
2145 database
= path_join(arg_root
, CATALOG_DATABASE
);
2151 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2152 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2154 log_error_errno(r
, "Failed to list catalog: %m");
2156 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2158 (void) pager_open(arg_pager_flags
);
2161 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2163 r
= catalog_list(stdout
, database
, oneline
);
2165 log_error_errno(r
, "Failed to list catalog: %m");
2175 case ACTION_RELINQUISH_VAR
:
2176 r
= relinquish_var();
2188 case ACTION_PRINT_HEADER
:
2190 case ACTION_DISK_USAGE
:
2191 case ACTION_LIST_BOOTS
:
2193 case ACTION_ROTATE_AND_VACUUM
:
2194 case ACTION_LIST_FIELDS
:
2195 case ACTION_LIST_FIELD_NAMES
:
2196 /* These ones require access to the journal files, continue below. */
2200 assert_not_reached("Unknown action");
2204 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2206 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2207 else if (arg_file_stdin
)
2208 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2210 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2211 else if (arg_machine
) {
2212 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2213 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2214 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2217 if (geteuid() != 0) {
2218 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2219 * the container, thus we need root privileges to override them. */
2220 r
= log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2224 r
= sd_bus_open_system(&bus
);
2226 log_error_errno(r
, "Failed to open system bus: %m");
2230 r
= sd_bus_call_method(
2232 "org.freedesktop.machine1",
2233 "/org/freedesktop/machine1",
2234 "org.freedesktop.machine1.Manager",
2235 "OpenMachineRootDirectory",
2240 log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2244 r
= sd_bus_message_read(reply
, "h", &fd
);
2246 bus_log_parse_error(r
);
2250 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2252 r
= log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2256 r
= sd_journal_open_directory_fd(&j
, fd
, SD_JOURNAL_OS_ROOT
);
2260 r
= sd_journal_open_namespace(
2263 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2264 arg_namespace_flags
| arg_journal_type
);
2266 log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2270 r
= journal_access_check_and_warn(j
, arg_quiet
,
2271 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2275 switch (arg_action
) {
2277 case ACTION_NEW_ID128
:
2278 case ACTION_SETUP_KEYS
:
2279 case ACTION_LIST_CATALOG
:
2280 case ACTION_DUMP_CATALOG
:
2281 case ACTION_UPDATE_CATALOG
:
2285 assert_not_reached("Unexpected action.");
2287 case ACTION_PRINT_HEADER
:
2288 journal_print_header(j
);
2296 case ACTION_DISK_USAGE
: {
2298 char sbytes
[FORMAT_BYTES_MAX
];
2300 r
= sd_journal_get_usage(j
, &bytes
);
2304 printf("Archived and active journals take up %s in the file system.\n",
2305 format_bytes(sbytes
, sizeof(sbytes
), bytes
));
2309 case ACTION_LIST_BOOTS
:
2313 case ACTION_ROTATE_AND_VACUUM
:
2321 case ACTION_VACUUM
: {
2325 HASHMAP_FOREACH(d
, j
->directories_by_path
, i
) {
2328 q
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2330 log_error_errno(q
, "Failed to vacuum %s: %m", d
->path
);
2338 case ACTION_LIST_FIELD_NAMES
: {
2341 SD_JOURNAL_FOREACH_FIELD(j
, field
) {
2342 printf("%s\n", field
);
2351 case ACTION_LIST_FIELDS
:
2355 assert_not_reached("Unknown action");
2358 if (arg_boot_offset
!= 0 &&
2359 sd_journal_has_runtime_files(j
) > 0 &&
2360 sd_journal_has_persistent_files(j
) == 0) {
2361 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2365 /* add_boot() must be called first!
2366 * It may need to seek the journal to find parent boot IDs. */
2377 log_error_errno(r
, "Failed to add filter for units: %m");
2381 r
= add_syslog_identifier(j
);
2383 log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2387 r
= add_priorities(j
);
2391 r
= add_facilities(j
);
2395 r
= add_matches(j
, argv
+ optind
);
2399 if (DEBUG_LOGGING
) {
2400 _cleanup_free_
char *filter
;
2402 filter
= journal_make_match_string(j
);
2406 log_debug("Journal filter: %s", filter
);
2409 if (arg_action
== ACTION_LIST_FIELDS
) {
2415 r
= sd_journal_set_data_threshold(j
, 0);
2417 log_error_errno(r
, "Failed to unset data size threshold: %m");
2421 r
= sd_journal_query_unique(j
, arg_field
);
2423 log_error_errno(r
, "Failed to query unique data objects: %m");
2427 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2430 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2433 eq
= memchr(data
, '=', size
);
2435 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2437 printf("%.*s\n", (int) size
, (const char*) data
);
2446 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2448 poll_fd
= sd_journal_get_fd(j
);
2449 if (poll_fd
== -EMFILE
) {
2450 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2452 } else if (poll_fd
== -EMEDIUMTYPE
) {
2453 log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2455 } else if (poll_fd
< 0) {
2456 log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2461 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2462 _cleanup_free_
char *cursor_from_file
= NULL
;
2463 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2465 if (arg_cursor_file
) {
2466 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2467 if (r
< 0 && r
!= -ENOENT
) {
2468 log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2473 cursor
= cursor_from_file
;
2474 after_cursor
= true;
2477 after_cursor
= !!arg_after_cursor
;
2480 r
= sd_journal_seek_cursor(j
, cursor
);
2482 log_error_errno(r
, "Failed to seek to cursor: %m");
2491 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2493 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2495 if (after_cursor
&& r
< 2) {
2496 /* We couldn't find the next entry after the cursor. */
2503 } else if (arg_since_set
&& !arg_reverse
) {
2504 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2506 log_error_errno(r
, "Failed to seek to date: %m");
2509 r
= sd_journal_next(j
);
2511 } else if (arg_until_set
&& arg_reverse
) {
2512 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2514 log_error_errno(r
, "Failed to seek to date: %m");
2517 r
= sd_journal_previous(j
);
2519 } else if (arg_reverse
) {
2520 r
= sd_journal_seek_tail(j
);
2522 log_error_errno(r
, "Failed to seek to tail: %m");
2526 r
= sd_journal_previous(j
);
2528 } else if (arg_lines
>= 0) {
2529 r
= sd_journal_seek_tail(j
);
2531 log_error_errno(r
, "Failed to seek to tail: %m");
2535 r
= sd_journal_previous_skip(j
, arg_lines
);
2538 r
= sd_journal_seek_head(j
);
2540 log_error_errno(r
, "Failed to seek to head: %m");
2544 r
= sd_journal_next(j
);
2548 log_error_errno(r
, "Failed to iterate through journal: %m");
2555 (void) pager_open(arg_pager_flags
);
2557 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
)) {
2559 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2561 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2563 log_error_errno(r
, "Failed to get cutoff: %m");
2569 printf("-- Logs begin at %s. --\n",
2570 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2572 printf("-- Logs begin at %s, end at %s. --\n",
2573 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2574 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2579 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2581 size_t highlight
[2] = {};
2585 r
= sd_journal_next(j
);
2587 r
= sd_journal_previous(j
);
2589 log_error_errno(r
, "Failed to iterate through journal: %m");
2596 if (arg_until_set
&& !arg_reverse
) {
2599 r
= sd_journal_get_realtime_usec(j
, &usec
);
2601 log_error_errno(r
, "Failed to determine timestamp: %m");
2604 if (usec
> arg_until
)
2608 if (arg_since_set
&& arg_reverse
) {
2611 r
= sd_journal_get_realtime_usec(j
, &usec
);
2613 log_error_errno(r
, "Failed to determine timestamp: %m");
2616 if (usec
< arg_since
)
2620 if (!arg_merge
&& !arg_quiet
) {
2623 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2625 if (previous_boot_id_valid
&&
2626 !sd_id128_equal(boot_id
, previous_boot_id
))
2627 printf("%s-- Reboot --%s\n",
2628 ansi_highlight(), ansi_normal());
2630 previous_boot_id
= boot_id
;
2631 previous_boot_id_valid
= true;
2636 if (arg_compiled_pattern
) {
2637 _cleanup_(pcre2_match_data_freep
) pcre2_match_data
*md
= NULL
;
2638 const void *message
;
2642 md
= pcre2_match_data_create(1, NULL
);
2646 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2653 log_error_errno(r
, "Failed to get MESSAGE field: %m");
2657 assert_se(message
= startswith(message
, "MESSAGE="));
2659 r
= pcre2_match(arg_compiled_pattern
,
2661 len
- strlen("MESSAGE="),
2662 0, /* start at offset 0 in the subject */
2663 0, /* default options */
2666 if (r
== PCRE2_ERROR_NOMATCH
) {
2671 unsigned char buf
[LINE_MAX
];
2674 r2
= pcre2_get_error_message(r
, buf
, sizeof buf
);
2675 log_error("Pattern matching failed: %s",
2676 r2
< 0 ? "unknown error" : (char*) buf
);
2681 ovec
= pcre2_get_ovector_pointer(md
);
2682 highlight
[0] = ovec
[0];
2683 highlight
[1] = ovec
[1];
2688 arg_all
* OUTPUT_SHOW_ALL
|
2689 arg_full
* OUTPUT_FULL_WIDTH
|
2690 colors_enabled() * OUTPUT_COLOR
|
2691 arg_catalog
* OUTPUT_CATALOG
|
2692 arg_utc
* OUTPUT_UTC
|
2693 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2695 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2696 arg_output_fields
, highlight
, &ellipsized
);
2698 if (r
== -EADDRNOTAVAIL
)
2705 /* If journalctl take a long time to process messages, and during that time journal file
2706 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2707 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2708 * in the "following" case. By periodically calling sd_journal_process() during the processing
2709 * loop we shrink the window of time a client instance has open file descriptors for rotated
2710 * (deleted) journal files. */
2711 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2712 r
= sd_journal_process(j
);
2714 log_error_errno(r
, "Failed to process inotify events: %m");
2721 if (n_shown
== 0 && !arg_quiet
)
2722 printf("-- No entries --\n");
2728 r
= wait_for_change(j
, poll_fd
);
2735 if (arg_show_cursor
|| arg_cursor_file
) {
2736 _cleanup_free_
char *cursor
= NULL
;
2738 r
= sd_journal_get_cursor(j
, &cursor
);
2739 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2740 log_error_errno(r
, "Failed to get cursor: %m");
2742 if (arg_show_cursor
)
2743 printf("-- cursor: %s\n", cursor
);
2745 if (arg_cursor_file
) {
2746 r
= write_string_file(arg_cursor_file
, cursor
,
2747 WRITE_STRING_FILE_CREATE
|
2748 WRITE_STRING_FILE_ATOMIC
);
2751 "Failed to write new cursor to %s: %m",
2760 strv_free(arg_file
);
2762 set_free(arg_facilities
);
2763 strv_free(arg_syslog_identifier
);
2764 strv_free(arg_system_units
);
2765 strv_free(arg_user_units
);
2766 strv_free(arg_output_fields
);
2769 free(arg_verify_key
);
2772 if (arg_compiled_pattern
) {
2773 pcre2_code_free(arg_compiled_pattern
);
2775 /* --grep was used, no error was thrown, but the pattern didn't
2776 * match anything. Let's mimic grep's behavior here and return
2777 * a non-zero exit code, so journalctl --grep can be used
2778 * in scripts and such */
2779 if (r
== 0 && n_shown
== 0)
2784 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;