1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include <sys/inotify.h>
17 #include "sd-device.h"
18 #include "sd-journal.h"
21 #include "alloc-util.h"
23 #include "bus-error.h"
24 #include "bus-locator.h"
28 #include "chattr-util.h"
29 #include "constants.h"
30 #include "devnum-util.h"
31 #include "dissect-image.h"
34 #include "format-table.h"
35 #include "format-util.h"
38 #include "glob-util.h"
39 #include "hostname-util.h"
40 #include "id128-print.h"
42 #include "journal-def.h"
43 #include "journal-internal.h"
44 #include "journal-util.h"
45 #include "journal-vacuum.h"
46 #include "journal-verify.h"
47 #include "locale-util.h"
49 #include "logs-show.h"
50 #include "main-func.h"
51 #include "memory-util.h"
52 #include "missing_sched.h"
54 #include "mount-util.h"
55 #include "mountpoint-util.h"
56 #include "nulstr-util.h"
58 #include "parse-argument.h"
59 #include "parse-util.h"
60 #include "path-util.h"
61 #include "pcre2-util.h"
62 #include "pretty-print.h"
63 #include "qrcode-util.h"
64 #include "random-util.h"
65 #include "rlimit-util.h"
68 #include "signal-util.h"
69 #include "static-destruct.h"
70 #include "stdio-util.h"
71 #include "string-table.h"
73 #include "syslog-util.h"
74 #include "terminal-util.h"
75 #include "tmpfile-util.h"
76 #include "unit-name.h"
77 #include "user-util.h"
80 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
81 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
84 /* Special values for arg_lines */
85 ARG_LINES_DEFAULT
= -2,
89 static OutputMode arg_output
= OUTPUT_SHORT
;
90 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
91 static bool arg_utc
= false;
92 static bool arg_follow
= false;
93 static bool arg_full
= true;
94 static bool arg_all
= false;
95 static PagerFlags arg_pager_flags
= 0;
96 static int arg_lines
= ARG_LINES_DEFAULT
;
97 static bool arg_no_tail
= false;
98 static bool arg_quiet
= false;
99 static bool arg_merge
= false;
100 static bool arg_boot
= false;
101 static sd_id128_t arg_boot_id
= {};
102 static int arg_boot_offset
= 0;
103 static bool arg_dmesg
= false;
104 static bool arg_no_hostname
= false;
105 static const char *arg_cursor
= NULL
;
106 static const char *arg_cursor_file
= NULL
;
107 static const char *arg_after_cursor
= NULL
;
108 static bool arg_show_cursor
= false;
109 static const char *arg_directory
= NULL
;
110 static char **arg_file
= NULL
;
111 static bool arg_file_stdin
= false;
112 static int arg_priorities
= 0xFF;
113 static Set
*arg_facilities
= NULL
;
114 static char *arg_verify_key
= NULL
;
116 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
117 static bool arg_force
= false;
119 static usec_t arg_since
= 0, arg_until
= 0;
120 static bool arg_since_set
= false, arg_until_set
= false;
121 static char **arg_syslog_identifier
= NULL
;
122 static char **arg_system_units
= NULL
;
123 static char **arg_user_units
= NULL
;
124 static const char *arg_field
= NULL
;
125 static bool arg_catalog
= false;
126 static bool arg_reverse
= false;
127 static int arg_journal_type
= 0;
128 static int arg_namespace_flags
= 0;
129 static char *arg_root
= NULL
;
130 static char *arg_image
= NULL
;
131 static const char *arg_machine
= NULL
;
132 static const char *arg_namespace
= NULL
;
133 static uint64_t arg_vacuum_size
= 0;
134 static uint64_t arg_vacuum_n_files
= 0;
135 static usec_t arg_vacuum_time
= 0;
136 static Set
*arg_output_fields
= NULL
;
137 static const char *arg_pattern
= NULL
;
138 static pcre2_code
*arg_compiled_pattern
= NULL
;
139 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
140 ImagePolicy
*arg_image_policy
= NULL
;
142 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
143 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
144 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
148 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
151 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
152 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
163 ACTION_UPDATE_CATALOG
,
166 ACTION_RELINQUISH_VAR
,
170 ACTION_ROTATE_AND_VACUUM
,
172 ACTION_LIST_FIELD_NAMES
,
173 } arg_action
= ACTION_SHOW
;
175 typedef struct BootId
{
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 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
192 "Devpath does not start with /dev/");
194 if (stat(devpath
, &st
) < 0)
195 return log_error_errno(errno
, "Couldn't stat file: %m");
197 r
= sd_device_new_from_stat_rdev(&device
, &st
);
199 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
201 for (d
= device
; d
; ) {
202 _cleanup_free_
char *match
= NULL
;
203 const char *subsys
, *sysname
, *devnode
;
206 r
= sd_device_get_subsystem(d
, &subsys
);
210 r
= sd_device_get_sysname(d
, &sysname
);
214 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
218 r
= sd_journal_add_match(j
, match
, 0);
220 return log_error_errno(r
, "Failed to add match: %m");
222 if (sd_device_get_devname(d
, &devnode
) >= 0) {
223 _cleanup_free_
char *match1
= NULL
;
225 r
= stat(devnode
, &st
);
227 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
229 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
233 r
= sd_journal_add_match(j
, match1
, 0);
235 return log_error_errno(r
, "Failed to add match: %m");
239 if (sd_device_get_parent(d
, &parent
) < 0)
245 r
= add_match_this_boot(j
, arg_machine
);
247 return log_error_errno(r
, "Failed to add match for the current boot: %m");
252 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
255 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
257 return format_timestamp(buf
, l
, t
);
260 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
261 sd_id128_t id
= SD_ID128_NULL
;
264 if (streq(x
, "all")) {
265 *boot_id
= SD_ID128_NULL
;
268 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
271 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
272 r
= sd_id128_from_string(t
, &id
);
274 x
+= SD_ID128_STRING_MAX
- 1;
276 if (!IN_SET(*x
, 0, '-', '+'))
280 r
= safe_atoi(x
, &off
);
285 r
= safe_atoi(x
, &off
);
299 static int help_facilities(void) {
301 puts("Available facilities:");
303 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
304 _cleanup_free_
char *t
= NULL
;
306 if (log_facility_unshifted_to_string_alloc(i
, &t
))
314 static int help(void) {
315 _cleanup_free_
char *link
= NULL
;
318 pager_open(arg_pager_flags
);
320 r
= terminal_urlify_man("journalctl", "1", &link
);
324 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
325 "%5$sQuery the journal.%6$s\n\n"
326 "%3$sSource Options:%4$s\n"
327 " --system Show the system journal\n"
328 " --user Show the user journal for the current user\n"
329 " -M --machine=CONTAINER Operate on local container\n"
330 " -m --merge Show entries from all available journals\n"
331 " -D --directory=PATH Show journal files from directory\n"
332 " --file=PATH Show journal file\n"
333 " --root=PATH Operate on an alternate filesystem root\n"
334 " --image=PATH Operate on disk image as filesystem root\n"
335 " --image-policy=POLICY Specify disk image dissection policy\n"
336 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
337 "\n%3$sFiltering Options:%4$s\n"
338 " -S --since=DATE Show entries not older than the specified date\n"
339 " -U --until=DATE Show entries not newer than the specified date\n"
340 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
341 " --after-cursor=CURSOR Show entries after the specified cursor\n"
342 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
343 " -b --boot[=ID] Show current boot or the specified boot\n"
344 " -u --unit=UNIT Show logs from the specified unit\n"
345 " --user-unit=UNIT Show logs from the specified user unit\n"
346 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
347 " -p --priority=RANGE Show entries with the specified priority\n"
348 " --facility=FACILITY... Show entries with the specified facilities\n"
349 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
350 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
351 " -k --dmesg Show kernel message log from the current boot\n"
352 "\n%3$sOutput Control Options:%4$s\n"
353 " -o --output=STRING Change journal output mode (short, short-precise,\n"
354 " short-iso, short-iso-precise, short-full,\n"
355 " short-monotonic, short-unix, verbose, export,\n"
356 " json, json-pretty, json-sse, json-seq, cat,\n"
358 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
359 " -n --lines[=INTEGER] Number of journal entries to show\n"
360 " -r --reverse Show the newest entries first\n"
361 " --show-cursor Print the cursor after all the entries\n"
362 " --utc Express time in Coordinated Universal Time (UTC)\n"
363 " -x --catalog Add message explanations where available\n"
364 " --no-hostname Suppress output of hostname field\n"
365 " --no-full Ellipsize fields\n"
366 " -a --all Show all fields, including long and unprintable\n"
367 " -f --follow Follow the journal\n"
368 " --no-tail Show all lines, even in follow mode\n"
369 " -q --quiet Do not show info messages and privilege warning\n"
370 "\n%3$sPager Control Options:%4$s\n"
371 " --no-pager Do not pipe output into a pager\n"
372 " -e --pager-end Immediately jump to the end in the pager\n"
373 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
374 " --interval=TIME Time interval for changing the FSS sealing key\n"
375 " --verify-key=KEY Specify FSS verification key\n"
376 " --force Override of the FSS key pair with --setup-keys\n"
377 "\n%3$sCommands:%4$s\n"
378 " -h --help Show this help text\n"
379 " --version Show package version\n"
380 " -N --fields List all field names currently used\n"
381 " -F --field=FIELD List all values that a specified field takes\n"
382 " --list-boots Show terse information about recorded boots\n"
383 " --disk-usage Show total disk usage of all journal files\n"
384 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
385 " --vacuum-files=INT Leave only the specified number of journal files\n"
386 " --vacuum-time=TIME Remove journal files older than specified time\n"
387 " --verify Verify journal file consistency\n"
388 " --sync Synchronize unwritten journal messages to disk\n"
389 " --relinquish-var Stop logging to disk, log to temporary file system\n"
390 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
391 " --flush Flush all journal data from /run into /var\n"
392 " --rotate Request immediate rotation of the journal files\n"
393 " --header Show journal header information\n"
394 " --list-catalog Show all message IDs in the catalog\n"
395 " --dump-catalog Show entries in the message catalog\n"
396 " --update-catalog Update the message catalog database\n"
397 " --setup-keys Generate a new FSS key pair\n"
398 "\nSee the %2$s for details.\n",
399 program_invocation_short_name
,
409 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 { "image", required_argument
, NULL
, ARG_IMAGE
},
481 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
482 { "header", no_argument
, NULL
, ARG_HEADER
},
483 { "identifier", required_argument
, NULL
, 't' },
484 { "priority", required_argument
, NULL
, 'p' },
485 { "facility", required_argument
, NULL
, ARG_FACILITY
},
486 { "grep", required_argument
, NULL
, 'g' },
487 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
488 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
489 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
490 { "verify", no_argument
, NULL
, ARG_VERIFY
},
491 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
492 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
493 { "cursor", required_argument
, NULL
, 'c' },
494 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
495 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
496 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
497 { "since", required_argument
, NULL
, 'S' },
498 { "until", required_argument
, NULL
, 'U' },
499 { "unit", required_argument
, NULL
, 'u' },
500 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
501 { "field", required_argument
, NULL
, 'F' },
502 { "fields", no_argument
, NULL
, 'N' },
503 { "catalog", no_argument
, NULL
, 'x' },
504 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
505 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
506 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
507 { "reverse", no_argument
, NULL
, 'r' },
508 { "machine", required_argument
, NULL
, 'M' },
509 { "utc", no_argument
, NULL
, ARG_UTC
},
510 { "flush", no_argument
, NULL
, ARG_FLUSH
},
511 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
512 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
513 { "sync", no_argument
, NULL
, ARG_SYNC
},
514 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
515 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
516 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
517 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
518 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
519 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
520 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
529 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
540 arg_pager_flags
|= PAGER_DISABLE
;
544 arg_pager_flags
|= PAGER_JUMP_TO_END
;
546 if (arg_lines
== ARG_LINES_DEFAULT
)
558 if (streq(optarg
, "help")) {
559 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
563 arg_output
= output_mode_from_string(optarg
);
565 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
567 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
570 if (OUTPUT_MODE_IS_JSON(arg_output
))
571 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
573 arg_json_format_flags
= JSON_FORMAT_OFF
;
591 if (streq(optarg
, "all"))
592 arg_lines
= ARG_LINES_ALL
;
594 r
= safe_atoi(optarg
, &arg_lines
);
595 if (r
< 0 || arg_lines
< 0)
596 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
601 /* Hmm, no argument? Maybe the next
602 * word on the command line is
603 * supposed to be the argument? Let's
604 * see if there is one, and is
608 if (streq(argv
[optind
], "all")) {
609 arg_lines
= ARG_LINES_ALL
;
611 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
625 arg_action
= ACTION_NEW_ID128
;
638 arg_boot_id
= SD_ID128_NULL
;
644 arg_boot_id
= SD_ID128_NULL
;
648 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
650 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
654 /* Hmm, no argument? Maybe the next
655 * word on the command line is
656 * supposed to be the argument? Let's
657 * see if there is one and is parsable
658 * as a boot descriptor... */
659 } else if (optind
< argc
) {
660 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
669 arg_action
= ACTION_LIST_BOOTS
;
673 arg_boot
= arg_dmesg
= true;
677 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
681 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
685 arg_machine
= optarg
;
689 if (streq(optarg
, "*")) {
690 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
691 arg_namespace
= NULL
;
692 } else if (startswith(optarg
, "+")) {
693 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
694 arg_namespace
= optarg
+ 1;
695 } else if (isempty(optarg
)) {
696 arg_namespace_flags
= 0;
697 arg_namespace
= NULL
;
699 arg_namespace_flags
= 0;
700 arg_namespace
= optarg
;
706 arg_directory
= optarg
;
710 if (streq(optarg
, "-"))
711 /* An undocumented feature: we can read journal files from STDIN. We don't document
712 * this though, since after all we only support this for mmap-able, seekable files, and
713 * not for example pipes which are probably the primary usecase for reading things from
714 * STDIN. To avoid confusion we hence don't document this feature. */
715 arg_file_stdin
= true;
717 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
719 return log_error_errno(r
, "Failed to add paths: %m");
724 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
730 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
735 case ARG_IMAGE_POLICY
:
736 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
745 case ARG_CURSOR_FILE
:
746 arg_cursor_file
= optarg
;
749 case ARG_AFTER_CURSOR
:
750 arg_after_cursor
= optarg
;
753 case ARG_SHOW_CURSOR
:
754 arg_show_cursor
= true;
758 arg_action
= ACTION_PRINT_HEADER
;
762 arg_action
= ACTION_VERIFY
;
766 arg_action
= ACTION_DISK_USAGE
;
769 case ARG_VACUUM_SIZE
:
770 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
772 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
774 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
777 case ARG_VACUUM_FILES
:
778 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
780 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
782 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
785 case ARG_VACUUM_TIME
:
786 r
= parse_sec(optarg
, &arg_vacuum_time
);
788 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
790 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
799 arg_action
= ACTION_SETUP_KEYS
;
803 r
= free_and_strdup(&arg_verify_key
, optarg
);
806 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
807 * in ps or htop output. */
808 memset(optarg
, 'x', strlen(optarg
));
810 arg_action
= ACTION_VERIFY
;
815 r
= parse_sec(optarg
, &arg_interval
);
816 if (r
< 0 || arg_interval
<= 0)
817 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
818 "Failed to parse sealing key change interval: %s", optarg
);
825 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
826 "Compiled without forward-secure sealing support.");
832 dots
= strstr(optarg
, "..");
834 _cleanup_free_
char *a
= NULL
;
838 a
= strndup(optarg
, dots
- optarg
);
842 from
= log_level_from_string(a
);
843 to
= log_level_from_string(dots
+ 2);
845 if (from
< 0 || to
< 0)
846 return log_error_errno(from
< 0 ? from
: to
,
847 "Failed to parse log level range %s", optarg
);
852 for (i
= from
; i
<= to
; i
++)
853 arg_priorities
|= 1 << i
;
855 for (i
= to
; i
<= from
; i
++)
856 arg_priorities
|= 1 << i
;
862 p
= log_level_from_string(optarg
);
864 return log_error_errno(p
, "Unknown log level %s", optarg
);
868 for (i
= 0; i
<= p
; i
++)
869 arg_priorities
|= 1 << i
;
879 _cleanup_free_
char *fac
= NULL
;
882 r
= extract_first_word(&p
, &fac
, ",", 0);
884 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
888 if (streq(fac
, "help")) {
893 num
= log_facility_unshifted_from_string(fac
);
895 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
897 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
905 arg_pattern
= optarg
;
908 case ARG_CASE_SENSITIVE
:
910 r
= parse_boolean(optarg
);
912 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
913 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
915 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
920 r
= parse_timestamp(optarg
, &arg_since
);
922 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
923 "Failed to parse timestamp: %s", optarg
);
924 arg_since_set
= true;
928 r
= parse_timestamp(optarg
, &arg_until
);
930 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
931 "Failed to parse timestamp: %s", optarg
);
932 arg_until_set
= true;
936 r
= strv_extend(&arg_syslog_identifier
, optarg
);
942 r
= strv_extend(&arg_system_units
, optarg
);
948 r
= strv_extend(&arg_user_units
, optarg
);
954 arg_action
= ACTION_LIST_FIELDS
;
959 arg_action
= ACTION_LIST_FIELD_NAMES
;
962 case ARG_NO_HOSTNAME
:
963 arg_no_hostname
= true;
970 case ARG_LIST_CATALOG
:
971 arg_action
= ACTION_LIST_CATALOG
;
974 case ARG_DUMP_CATALOG
:
975 arg_action
= ACTION_DUMP_CATALOG
;
978 case ARG_UPDATE_CATALOG
:
979 arg_action
= ACTION_UPDATE_CATALOG
;
991 arg_action
= ACTION_FLUSH
;
994 case ARG_SMART_RELINQUISH_VAR
: {
995 int root_mnt_id
, log_mnt_id
;
997 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
998 * if it's on the same mount as the root file system there's no point in
999 * relinquishing access and we can leave journald write to it until the very last
1002 r
= path_get_mnt_id("/", &root_mnt_id
);
1004 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1006 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1008 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1009 else if (root_mnt_id
== log_mnt_id
) {
1010 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1013 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1019 case ARG_RELINQUISH_VAR
:
1020 arg_action
= ACTION_RELINQUISH_VAR
;
1024 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1028 arg_action
= ACTION_SYNC
;
1031 case ARG_OUTPUT_FIELDS
: {
1032 _cleanup_strv_free_
char **v
= NULL
;
1034 v
= strv_split(optarg
, ",");
1038 r
= set_put_strdupv(&arg_output_fields
, v
);
1048 assert_not_reached();
1052 arg_lines
= ARG_LINES_ALL
;
1054 if (arg_follow
&& !arg_since_set
&& arg_lines
== ARG_LINES_DEFAULT
)
1057 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1059 arg_boot_id
= SD_ID128_NULL
;
1060 arg_boot_offset
= 0;
1063 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1064 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1065 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1067 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1068 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1069 "--since= must be before --until=.");
1071 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1072 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1073 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1075 if (arg_follow
&& arg_reverse
)
1076 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1077 "Please specify either --reverse= or --follow=, not both.");
1079 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1080 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1081 "Extraneous arguments starting with '%s'",
1084 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1085 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1086 "Using --boot or --list-boots with --merge is not supported.");
1088 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1089 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1090 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1091 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1092 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1096 arg_system_units
= strv_free(arg_system_units
);
1100 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1104 /* When --grep is used along with --lines, we don't know how many lines we can print.
1105 * So we search backwards and count until enough lines have been printed or we hit the head.
1106 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1107 * if that is specified. */
1108 if (arg_lines
>= 0 && !arg_follow
)
1115 static int add_matches(sd_journal
*j
, char **args
) {
1116 bool have_term
= false;
1120 STRV_FOREACH(i
, args
) {
1123 if (streq(*i
, "+")) {
1126 r
= sd_journal_add_disjunction(j
);
1129 } else if (path_is_absolute(*i
)) {
1130 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1133 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1135 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1137 if (lstat(p
, &st
) < 0)
1138 return log_error_errno(errno
, "Couldn't stat file: %m");
1140 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1141 if (executable_is_script(p
, &interpreter
) > 0) {
1142 _cleanup_free_
char *comm
= NULL
;
1144 r
= path_extract_filename(p
, &comm
);
1146 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1148 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1152 /* Append _EXE only if the interpreter is not a link.
1153 Otherwise, it might be outdated often. */
1154 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1155 t2
= strjoin("_EXE=", interpreter
);
1160 t
= strjoin("_EXE=", p
);
1165 r
= sd_journal_add_match(j
, t
, 0);
1168 r
= sd_journal_add_match(j
, t2
, 0);
1170 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1171 r
= add_matches_for_device(j
, p
);
1175 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1176 "File is neither a device node, nor regular file, nor executable: %s",
1181 r
= sd_journal_add_match(j
, *i
, 0);
1186 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1189 if (!strv_isempty(args
) && !have_term
)
1190 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1191 "\"+\" can only be used between terms");
1196 static int discover_next_boot(
1198 sd_id128_t previous_boot_id
,
1208 /* We expect the journal to be on the last position of a boot
1209 * (in relation to the direction we are going), so that the next
1210 * invocation of sd_journal_next/previous will be from a different
1211 * boot. We then collect any information we desire and then jump
1212 * to the last location of the new boot by using a _BOOT_ID match
1213 * coming from the other journal direction. */
1215 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1216 * we can actually advance to a *different* boot. */
1217 sd_journal_flush_matches(j
);
1221 r
= sd_journal_previous(j
);
1223 r
= sd_journal_next(j
);
1228 return 0; /* End of journal, yay. */
1231 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot
.id
);
1235 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1236 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1237 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1238 * complete than the main entry array, and hence might reference an entry that's not actually the last
1239 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1240 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1243 } while (sd_id128_equal(boot
.id
, previous_boot_id
));
1245 r
= sd_journal_get_realtime_usec(j
, &boot
.first_usec
);
1249 /* Now seek to the last occurrence of this boot ID. */
1250 r
= add_match_boot_id(j
, boot
.id
);
1255 r
= sd_journal_seek_head(j
);
1257 r
= sd_journal_seek_tail(j
);
1262 r
= sd_journal_next(j
);
1264 r
= sd_journal_previous(j
);
1268 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1269 "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. */
1271 r
= sd_journal_get_realtime_usec(j
, &boot
.last_usec
);
1275 sd_journal_flush_matches(j
);
1280 static int find_boot_by_id(sd_journal
*j
) {
1285 sd_journal_flush_matches(j
);
1287 r
= add_match_boot_id(j
, arg_boot_id
);
1291 r
= sd_journal_seek_head(j
); /* seek to oldest */
1295 r
= sd_journal_next(j
); /* read the oldest entry */
1299 /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID.
1300 * After flushing the matches, one more invocation of _previous() will hence place us at the
1301 * following entry, which must then have an older boot ID */
1303 sd_journal_flush_matches(j
);
1307 static int find_boot_by_offset(sd_journal
*j
) {
1308 bool advance_older
, skip_once
;
1311 /* Adjust for the asymmetry that offset 0 is the last (and current) boot, while 1 is considered the
1312 * (chronological) first boot in the journal. */
1313 advance_older
= skip_once
= arg_boot_offset
<= 0;
1316 r
= sd_journal_seek_tail(j
); /* seek to newest */
1318 r
= sd_journal_seek_head(j
); /* seek to oldest */
1322 /* No sd_journal_next()/_previous() here.
1324 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1325 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1328 int offset
= arg_boot_offset
;
1329 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1333 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, &boot
);
1337 previous_boot_id
= boot
.id
;
1340 offset
+= advance_older
? 1 : -1;
1344 arg_boot_id
= boot
.id
;
1350 static int get_boots(sd_journal
*j
, BootId
**ret_boots
, size_t *ret_n_boots
) {
1351 _cleanup_free_ BootId
*boots
= NULL
;
1357 assert(ret_n_boots
);
1359 r
= sd_journal_seek_head(j
); /* seek to oldest */
1363 /* No sd_journal_next()/_previous() here.
1365 * At this point the read pointer is positioned before the oldest entry in the whole journal. The
1366 * next invocation of _next() will hence position us at the oldest entry we have. */
1368 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1372 r
= discover_next_boot(j
, previous_boot_id
, /* advance_older = */ false, &boot
);
1378 previous_boot_id
= boot
.id
;
1380 FOREACH_ARRAY(i
, boots
, n_boots
)
1381 if (sd_id128_equal(i
->id
, boot
.id
))
1382 /* The boot id is already stored, something wrong with the journal files.
1383 * Exiting as otherwise this problem would cause an infinite loop. */
1386 if (!GREEDY_REALLOC(boots
, n_boots
+ 1))
1389 boots
[n_boots
++] = boot
;
1392 *ret_boots
= TAKE_PTR(boots
);
1393 *ret_n_boots
= n_boots
;
1397 static int list_boots(sd_journal
*j
) {
1398 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1399 _cleanup_free_ BootId
*boots
= NULL
;
1405 r
= get_boots(j
, &boots
, &n_boots
);
1407 return log_error_errno(r
, "Failed to determine boots: %m");
1411 table
= table_new("idx", "boot id", "first entry", "last entry");
1416 table_set_width(table
, 0);
1418 r
= table_set_json_field_name(table
, 0, "index");
1420 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1422 (void) table_set_sort(table
, (size_t) 0);
1423 (void) table_set_reverse(table
, 0, arg_reverse
);
1425 FOREACH_ARRAY(i
, boots
, n_boots
) {
1426 r
= table_add_many(table
,
1427 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1428 TABLE_SET_ALIGN_PERCENT
, 100,
1430 TABLE_TIMESTAMP
, i
->first_usec
,
1431 TABLE_TIMESTAMP
, i
->last_usec
);
1433 return table_log_add_error(r
);
1436 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1438 return table_log_print_error(r
);
1443 static int add_boot(sd_journal
*j
) {
1451 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1452 * We can do this only when we logs are coming from the current machine,
1453 * so take the slow path if log location is specified. */
1454 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1455 !arg_directory
&& !arg_file
&& !arg_root
)
1456 return add_match_this_boot(j
, arg_machine
);
1458 if (sd_id128_is_null(arg_boot_id
)) {
1459 r
= find_boot_by_offset(j
);
1461 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1464 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1465 "No journal boot entry found from the specified boot offset (%+i).",
1468 r
= find_boot_by_id(j
);
1470 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1471 SD_ID128_TO_STRING(arg_boot_id
));
1473 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1474 "No journal boot entry found from the specified boot ID (%s).",
1475 SD_ID128_TO_STRING(arg_boot_id
));
1478 r
= add_match_boot_id(j
, arg_boot_id
);
1480 return log_error_errno(r
, "Failed to add match: %m");
1482 r
= sd_journal_add_conjunction(j
);
1484 return log_error_errno(r
, "Failed to add conjunction: %m");
1489 static int add_dmesg(sd_journal
*j
) {
1496 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1497 STRLEN("_TRANSPORT=kernel"));
1499 return log_error_errno(r
, "Failed to add match: %m");
1501 r
= sd_journal_add_conjunction(j
);
1503 return log_error_errno(r
, "Failed to add conjunction: %m");
1508 static int get_possible_units(
1514 _cleanup_set_free_free_ Set
*found
= NULL
;
1517 found
= set_new(&string_hash_ops
);
1521 NULSTR_FOREACH(field
, fields
) {
1525 r
= sd_journal_query_unique(j
, field
);
1529 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1532 _cleanup_free_
char *u
= NULL
;
1534 eq
= memchr(data
, '=', size
);
1536 prefix
= eq
- (char*) data
+ 1;
1540 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1544 STRV_FOREACH(pattern
, patterns
)
1545 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1546 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1548 r
= set_consume(found
, u
);
1550 if (r
< 0 && r
!= -EEXIST
)
1558 *units
= TAKE_PTR(found
);
1563 /* This list is supposed to return the superset of unit names
1564 * possibly matched by rules added with add_matches_for_unit... */
1565 #define SYSTEM_UNITS \
1569 "OBJECT_SYSTEMD_UNIT\0" \
1572 /* ... and add_matches_for_user_unit */
1573 #define USER_UNITS \
1574 "_SYSTEMD_USER_UNIT\0" \
1576 "COREDUMP_USER_UNIT\0" \
1577 "OBJECT_SYSTEMD_USER_UNIT\0" \
1578 "_SYSTEMD_USER_SLICE\0"
1580 static int add_units(sd_journal
*j
) {
1581 _cleanup_strv_free_
char **patterns
= NULL
;
1586 STRV_FOREACH(i
, arg_system_units
) {
1587 _cleanup_free_
char *u
= NULL
;
1589 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1593 if (string_is_glob(u
)) {
1594 r
= strv_push(&patterns
, u
);
1599 r
= add_matches_for_unit(j
, u
);
1602 r
= sd_journal_add_disjunction(j
);
1609 if (!strv_isempty(patterns
)) {
1610 _cleanup_set_free_free_ Set
*units
= NULL
;
1613 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1617 SET_FOREACH(u
, units
) {
1618 r
= add_matches_for_unit(j
, u
);
1621 r
= sd_journal_add_disjunction(j
);
1628 patterns
= strv_free(patterns
);
1630 STRV_FOREACH(i
, arg_user_units
) {
1631 _cleanup_free_
char *u
= NULL
;
1633 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1637 if (string_is_glob(u
)) {
1638 r
= strv_push(&patterns
, u
);
1643 r
= add_matches_for_user_unit(j
, u
, getuid());
1646 r
= sd_journal_add_disjunction(j
);
1653 if (!strv_isempty(patterns
)) {
1654 _cleanup_set_free_free_ Set
*units
= NULL
;
1657 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1661 SET_FOREACH(u
, units
) {
1662 r
= add_matches_for_user_unit(j
, u
, getuid());
1665 r
= sd_journal_add_disjunction(j
);
1672 /* Complain if the user request matches but nothing whatsoever was
1673 * found, since otherwise everything would be matched. */
1674 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1677 r
= sd_journal_add_conjunction(j
);
1684 static int add_priorities(sd_journal
*j
) {
1685 char match
[] = "PRIORITY=0";
1689 if (arg_priorities
== 0xFF)
1692 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1693 if (arg_priorities
& (1 << i
)) {
1694 match
[sizeof(match
)-2] = '0' + i
;
1696 r
= sd_journal_add_match(j
, match
, strlen(match
));
1698 return log_error_errno(r
, "Failed to add match: %m");
1701 r
= sd_journal_add_conjunction(j
);
1703 return log_error_errno(r
, "Failed to add conjunction: %m");
1708 static int add_facilities(sd_journal
*j
) {
1712 SET_FOREACH(p
, arg_facilities
) {
1713 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1715 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1717 r
= sd_journal_add_match(j
, match
, strlen(match
));
1719 return log_error_errno(r
, "Failed to add match: %m");
1725 static int add_syslog_identifier(sd_journal
*j
) {
1730 STRV_FOREACH(i
, arg_syslog_identifier
) {
1731 _cleanup_free_
char *u
= NULL
;
1733 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1736 r
= sd_journal_add_match(j
, u
, 0);
1739 r
= sd_journal_add_disjunction(j
);
1744 r
= sd_journal_add_conjunction(j
);
1752 static int format_journal_url(
1761 _cleanup_free_
char *url
= NULL
;
1762 _cleanup_fclose_
FILE *f
= NULL
;
1763 size_t url_size
= 0;
1767 assert(seed_size
> 0);
1769 f
= open_memstream_unlocked(&url
, &url_size
);
1776 for (size_t i
= 0; i
< seed_size
; i
++) {
1777 if (i
> 0 && i
% 3 == 0)
1779 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1782 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1785 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1787 fprintf(f
, ";hostname=%s", hn
);
1790 r
= fflush_and_check(f
);
1799 *ret_url
= TAKE_PTR(url
);
1804 static int setup_keys(void) {
1806 size_t mpk_size
, seed_size
, state_size
;
1807 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1808 _cleanup_free_
char *p
= NULL
;
1809 uint8_t *mpk
, *seed
, *state
;
1810 _cleanup_close_
int fd
= -EBADF
;
1811 sd_id128_t machine
, boot
;
1816 r
= stat("/var/log/journal", &st
);
1817 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1818 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1820 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1821 log_error("%s is not a directory, must be using persistent logging for FSS.",
1822 "/var/log/journal");
1823 return r
< 0 ? -errno
: -ENOTDIR
;
1826 r
= sd_id128_get_machine(&machine
);
1828 return log_error_errno(r
, "Failed to get machine ID: %m");
1830 r
= sd_id128_get_boot(&boot
);
1832 return log_error_errno(r
, "Failed to get boot ID: %m");
1834 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1835 SD_ID128_FORMAT_VAL(machine
)) < 0)
1840 if (r
< 0 && errno
!= ENOENT
)
1841 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1842 } else if (access(p
, F_OK
) >= 0)
1843 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1844 "Sealing key file %s exists already. Use --force to recreate.", p
);
1846 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1847 SD_ID128_FORMAT_VAL(machine
)) < 0)
1850 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1851 mpk
= alloca_safe(mpk_size
);
1853 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1854 seed
= alloca_safe(seed_size
);
1856 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1857 state
= alloca_safe(state_size
);
1859 log_info("Generating seed...");
1860 r
= crypto_random_bytes(seed
, seed_size
);
1862 return log_error_errno(r
, "Failed to acquire random seed: %m");
1864 log_info("Generating key pair...");
1865 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1867 log_info("Generating sealing key...");
1868 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1870 assert(arg_interval
> 0);
1872 n
= now(CLOCK_REALTIME
);
1876 fd
= mkostemp_safe(k
);
1878 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1880 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1882 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1883 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1885 struct FSSHeader h
= {
1886 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1887 .machine_id
= machine
,
1889 .header_size
= htole64(sizeof(h
)),
1890 .start_usec
= htole64(n
* arg_interval
),
1891 .interval_usec
= htole64(arg_interval
),
1892 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1893 .fsprg_state_size
= htole64(state_size
),
1896 r
= loop_write(fd
, &h
, sizeof(h
), false);
1898 return log_error_errno(r
, "Failed to write header: %m");
1900 r
= loop_write(fd
, state
, state_size
, false);
1902 return log_error_errno(r
, "Failed to write state: %m");
1904 if (rename(k
, p
) < 0)
1905 return log_error_errno(errno
, "Failed to link file: %m");
1909 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1911 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1916 hn
= gethostname_malloc();
1918 hostname_cleanup(hn
);
1921 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1923 "The %ssecret sealing key%s has been written to the following local file.\n"
1924 "This key file is automatically updated when the sealing key is advanced.\n"
1925 "It should not be used on multiple hosts.\n"
1929 "The sealing key is automatically changed every %s.\n"
1931 "Please write down the following %ssecret verification key%s. It should be stored\n"
1932 "in a safe location and should not be saved locally on disk.\n"
1934 strempty(hn
), hn
? "/" : "",
1935 SD_ID128_FORMAT_VAL(machine
),
1936 ansi_highlight(), ansi_normal(),
1938 FORMAT_TIMESPAN(arg_interval
, 0),
1939 ansi_highlight(), ansi_normal(),
1940 ansi_highlight_red());
1947 fprintf(stderr
, "%s", ansi_normal());
1949 _cleanup_free_
char *url
= NULL
;
1950 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1954 (void) print_qrcode(stderr
,
1955 "To transfer the verification key to your phone scan the QR code below",
1962 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1963 "Forward-secure sealing not available.");
1967 static int verify(sd_journal
*j
, bool verbose
) {
1973 log_show_color(true);
1975 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1977 usec_t first
= 0, validated
= 0, last
= 0;
1980 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1981 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1984 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1986 /* If the key was invalid give up right-away. */
1989 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1991 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1992 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1994 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1995 if (validated
> 0) {
1996 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1997 "=> Validated from %s to %s, final %s entries not sealed.",
1998 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1999 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
2000 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
2001 } else if (last
> 0)
2002 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2003 "=> No sealing yet, %s of entries not sealed.",
2004 FORMAT_TIMESPAN(last
- first
, 0));
2006 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2007 "=> No sealing yet, no entries in file.");
2015 static int simple_varlink_call(const char *option
, const char *method
) {
2016 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2017 const char *error
, *fn
;
2021 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2023 fn
= arg_namespace
?
2024 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2025 "/run/systemd/journal/io.systemd.journal";
2027 r
= varlink_connect_address(&link
, fn
);
2029 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2031 (void) varlink_set_description(link
, "journal");
2032 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2034 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2036 return log_error_errno(r
, "Failed to execute varlink call: %m");
2038 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2039 "Failed to execute varlink call: %s", error
);
2044 static int flush_to_var(void) {
2045 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2046 return 0; /* Already flushed, no need to contact journald */
2047 if (errno
!= ENOENT
)
2048 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2050 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2053 static int relinquish_var(void) {
2054 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2057 static int rotate(void) {
2058 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2061 static int sync_journal(void) {
2062 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2065 static int action_list_fields(sd_journal
*j
) {
2072 r
= sd_journal_set_data_threshold(j
, 0);
2074 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2076 r
= sd_journal_query_unique(j
, arg_field
);
2078 return log_error_errno(r
, "Failed to query unique data objects: %m");
2080 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2083 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2086 eq
= memchr(data
, '=', size
);
2088 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2090 printf("%.*s\n", (int) size
, (const char*) data
);
2098 static int update_cursor(sd_journal
*j
) {
2099 _cleanup_free_
char *cursor
= NULL
;
2104 if (!arg_show_cursor
&& !arg_cursor_file
)
2107 r
= sd_journal_get_cursor(j
, &cursor
);
2108 if (r
== -EADDRNOTAVAIL
)
2111 return log_error_errno(r
, "Failed to get cursor: %m");
2113 if (arg_show_cursor
)
2114 printf("-- cursor: %s\n", cursor
);
2116 if (arg_cursor_file
) {
2117 r
= write_string_file(arg_cursor_file
, cursor
, WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_ATOMIC
);
2119 return log_error_errno(r
, "Failed to write new cursor to %s: %m", arg_cursor_file
);
2125 typedef struct Context
{
2126 sd_journal
*journal
;
2130 bool previous_boot_id_valid
;
2131 sd_id128_t previous_boot_id
;
2132 sd_id128_t previous_boot_id_output
;
2133 dual_timestamp previous_ts_output
;
2136 static int show(Context
*c
) {
2142 j
= ASSERT_PTR(c
->journal
);
2144 while (arg_lines
< 0 || n_shown
< arg_lines
|| arg_follow
) {
2146 size_t highlight
[2] = {};
2149 r
= sd_journal_step_one(j
, !arg_reverse
);
2151 return log_error_errno(r
, "Failed to iterate through journal: %m");
2156 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2157 /* If --lines= is set, we usually rely on the n_shown to tell us
2158 * when to stop. However, if --since= is set too, we may end up
2159 * having less than --lines= to output. In this case let's also
2160 * check if the entry is in range. */
2164 r
= sd_journal_get_realtime_usec(j
, &usec
);
2166 return log_error_errno(r
, "Failed to determine timestamp: %m");
2167 if (usec
> arg_until
)
2171 if (arg_since_set
&& (arg_reverse
|| !c
->since_seeked
)) {
2174 r
= sd_journal_get_realtime_usec(j
, &usec
);
2176 return log_error_errno(r
, "Failed to determine timestamp: %m");
2178 if (usec
< arg_since
) {
2180 break; /* Reached the earliest entry */
2182 /* arg_lines >= 0 (!since_seeked):
2183 * We jumped arg_lines back and it seems to be too much */
2184 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2186 return log_error_errno(r
, "Failed to seek to date: %m");
2187 c
->since_seeked
= true;
2189 c
->need_seek
= true;
2192 c
->since_seeked
= true; /* We're surely within the range of --since now */
2195 if (!arg_merge
&& !arg_quiet
) {
2198 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2200 if (c
->previous_boot_id_valid
&&
2201 !sd_id128_equal(boot_id
, c
->previous_boot_id
))
2202 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2203 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2205 c
->previous_boot_id
= boot_id
;
2206 c
->previous_boot_id_valid
= true;
2210 if (arg_compiled_pattern
) {
2211 const void *message
;
2214 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2217 c
->need_seek
= true;
2221 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2224 assert_se(message
= startswith(message
, "MESSAGE="));
2226 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2227 len
- strlen("MESSAGE="), highlight
);
2231 c
->need_seek
= true;
2237 arg_all
* OUTPUT_SHOW_ALL
|
2238 arg_full
* OUTPUT_FULL_WIDTH
|
2239 colors_enabled() * OUTPUT_COLOR
|
2240 arg_catalog
* OUTPUT_CATALOG
|
2241 arg_utc
* OUTPUT_UTC
|
2242 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2244 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2245 arg_output_fields
, highlight
, &c
->ellipsized
,
2246 &c
->previous_ts_output
, &c
->previous_boot_id_output
);
2247 c
->need_seek
= true;
2248 if (r
== -EADDRNOTAVAIL
)
2255 /* If journalctl take a long time to process messages, and during that time journal file
2256 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2257 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2258 * in the "following" case. By periodically calling sd_journal_process() during the processing
2259 * loop we shrink the window of time a client instance has open file descriptors for rotated
2260 * (deleted) journal files. */
2261 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2262 r
= sd_journal_process(j
);
2264 return log_error_errno(r
, "Failed to process inotify events: %m");
2271 static int show_and_fflush(Context
*c
, sd_event_source
*s
) {
2279 return sd_event_exit(sd_event_source_get_event(s
), r
);
2285 static int on_journal_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
2286 Context
*c
= ASSERT_PTR(userdata
);
2291 r
= sd_journal_process(c
->journal
);
2293 log_error_errno(r
, "Failed to process journal events: %m");
2294 return sd_event_exit(sd_event_source_get_event(s
), r
);
2297 return show_and_fflush(c
, s
);
2300 static int on_first_event(sd_event_source
*s
, void *userdata
) {
2301 return show_and_fflush(userdata
, s
);
2304 static int on_signal(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
2307 assert(IN_SET(si
->ssi_signo
, SIGTERM
, SIGINT
));
2309 return sd_event_exit(sd_event_source_get_event(s
), si
->ssi_signo
);
2312 static int setup_event(Context
*c
, int fd
, sd_event
**ret
) {
2313 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2321 r
= sd_event_default(&e
);
2323 return log_error_errno(r
, "Failed to allocate sd_event object: %m");
2325 (void) sd_event_add_signal(e
, NULL
, SIGTERM
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2326 (void) sd_event_add_signal(e
, NULL
, SIGINT
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2328 r
= sd_event_add_io(e
, NULL
, fd
, EPOLLIN
, &on_journal_event
, c
);
2330 return log_error_errno(r
, "Failed to add io event source for journal: %m");
2332 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2333 r
= sd_event_add_io(e
, NULL
, STDOUT_FILENO
, EPOLLHUP
|EPOLLERR
, NULL
, INT_TO_PTR(-ECANCELED
));
2335 return log_error_errno(r
, "Failed to add io event source for stdout: %m");
2337 if (arg_lines
!= 0 || arg_since_set
) {
2338 r
= sd_event_add_defer(e
, NULL
, on_first_event
, c
);
2340 return log_error_errno(r
, "Failed to add defer event source: %m");
2347 static int run(int argc
, char *argv
[]) {
2348 bool need_seek
= false, since_seeked
= false, use_cursor
= false, after_cursor
= false;
2349 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2350 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2351 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2352 _cleanup_close_
int machine_fd
= -EBADF
;
2353 int n_shown
, r
, poll_fd
= -EBADF
;
2355 setlocale(LC_ALL
, "");
2358 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2359 * split up into many files. */
2360 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2362 r
= parse_argv(argc
, argv
);
2369 r
= mount_image_privately_interactively(
2372 DISSECT_IMAGE_GENERIC_ROOT
|
2373 DISSECT_IMAGE_REQUIRE_ROOT
|
2374 DISSECT_IMAGE_VALIDATE_OS
|
2375 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2376 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2378 /* ret_dir_fd= */ NULL
,
2383 arg_root
= strdup(mounted_dir
);
2388 signal(SIGWINCH
, columns_lines_cache_reset
);
2391 switch (arg_action
) {
2393 case ACTION_NEW_ID128
:
2394 return id128_print_new(ID128_PRINT_PRETTY
);
2396 case ACTION_SETUP_KEYS
:
2397 return setup_keys();
2399 case ACTION_LIST_CATALOG
:
2400 case ACTION_DUMP_CATALOG
:
2401 case ACTION_UPDATE_CATALOG
: {
2402 _cleanup_free_
char *database
= NULL
;
2404 database
= path_join(arg_root
, CATALOG_DATABASE
);
2408 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2409 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2411 return log_error_errno(r
, "Failed to list catalog: %m");
2413 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2415 pager_open(arg_pager_flags
);
2418 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2420 r
= catalog_list(stdout
, database
, oneline
);
2422 return log_error_errno(r
, "Failed to list catalog: %m");
2429 return flush_to_var();
2431 case ACTION_RELINQUISH_VAR
:
2432 return relinquish_var();
2435 return sync_journal();
2441 case ACTION_PRINT_HEADER
:
2443 case ACTION_DISK_USAGE
:
2444 case ACTION_LIST_BOOTS
:
2446 case ACTION_ROTATE_AND_VACUUM
:
2447 case ACTION_LIST_FIELDS
:
2448 case ACTION_LIST_FIELD_NAMES
:
2449 /* These ones require access to the journal files, continue below. */
2453 assert_not_reached();
2457 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2459 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2460 else if (arg_file_stdin
)
2461 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2463 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2464 else if (arg_machine
) {
2465 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2466 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2467 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2471 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2472 * the container, thus we need root privileges to override them. */
2473 return log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2475 r
= sd_bus_open_system(&bus
);
2477 return log_error_errno(r
, "Failed to open system bus: %m");
2479 r
= bus_call_method(bus
, bus_machine_mgr
, "OpenMachineRootDirectory", &error
, &reply
, "s", arg_machine
);
2481 return log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2483 r
= sd_bus_message_read(reply
, "h", &fd
);
2485 return bus_log_parse_error(r
);
2487 machine_fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2489 return log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2491 r
= sd_journal_open_directory_fd(&j
, machine_fd
, SD_JOURNAL_OS_ROOT
);
2493 r
= sd_journal_open_namespace(
2496 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2497 arg_namespace_flags
| arg_journal_type
);
2499 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2501 r
= journal_access_check_and_warn(j
, arg_quiet
,
2502 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2506 switch (arg_action
) {
2508 case ACTION_NEW_ID128
:
2509 case ACTION_SETUP_KEYS
:
2510 case ACTION_LIST_CATALOG
:
2511 case ACTION_DUMP_CATALOG
:
2512 case ACTION_UPDATE_CATALOG
:
2516 assert_not_reached();
2518 case ACTION_PRINT_HEADER
:
2519 journal_print_header(j
);
2523 return verify(j
, !arg_quiet
);
2525 case ACTION_DISK_USAGE
: {
2528 r
= sd_journal_get_usage(j
, &bytes
);
2532 printf("Archived and active journals take up %s in the file system.\n",
2533 FORMAT_BYTES(bytes
));
2538 case ACTION_LIST_BOOTS
:
2539 return list_boots(j
);
2541 case ACTION_ROTATE_AND_VACUUM
:
2549 case ACTION_VACUUM
: {
2553 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2554 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2556 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2565 case ACTION_LIST_FIELD_NAMES
: {
2568 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2569 printf("%s\n", field
);
2575 case ACTION_LIST_FIELDS
:
2579 assert_not_reached();
2582 if (arg_boot_offset
!= 0 &&
2583 sd_journal_has_runtime_files(j
) > 0 &&
2584 sd_journal_has_persistent_files(j
) == 0) {
2585 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2587 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2592 /* add_boot() must be called first!
2593 * It may need to seek the journal to find parent boot IDs. */
2604 return log_error_errno(r
, "Failed to add filter for units: %m");
2606 r
= add_syslog_identifier(j
);
2608 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2610 r
= add_priorities(j
);
2614 r
= add_facilities(j
);
2618 r
= add_matches(j
, argv
+ optind
);
2622 if (DEBUG_LOGGING
) {
2623 _cleanup_free_
char *filter
= NULL
;
2625 filter
= journal_make_match_string(j
);
2629 log_debug("Journal filter: %s", filter
);
2632 if (arg_action
== ACTION_LIST_FIELDS
)
2633 return action_list_fields(j
);
2635 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2637 poll_fd
= sd_journal_get_fd(j
);
2638 if (poll_fd
== -EMFILE
) {
2639 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2641 } else if (poll_fd
== -EMEDIUMTYPE
)
2642 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2643 else if (poll_fd
< 0)
2644 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2647 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2648 _cleanup_free_
char *cursor_from_file
= NULL
;
2649 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2651 if (arg_cursor_file
) {
2652 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2653 if (r
< 0 && r
!= -ENOENT
)
2654 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2657 cursor
= cursor_from_file
;
2658 after_cursor
= true;
2661 after_cursor
= arg_after_cursor
;
2664 r
= sd_journal_seek_cursor(j
, cursor
);
2666 return log_error_errno(r
, "Failed to seek to cursor: %m");
2674 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2676 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2678 if (after_cursor
&& r
< 2) {
2679 /* We couldn't find the next entry after the cursor. */
2686 } else if (arg_until_set
&& (arg_reverse
|| arg_lines
>= 0)) {
2687 /* If both --until and any of --reverse and --lines is specified, things get
2688 * a little tricky. We seek to the place of --until first. If only --reverse or
2689 * --reverse and --lines is specified, we search backwards and let the output
2690 * counter handle --lines for us. If only --lines is used, we just jump backwards
2691 * arg_lines and search afterwards from there. */
2693 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2695 return log_error_errno(r
, "Failed to seek to date: %m");
2698 r
= sd_journal_previous(j
);
2699 else /* arg_lines >= 0 */
2700 r
= sd_journal_previous_skip(j
, arg_lines
);
2702 } else if (arg_reverse
) {
2703 r
= sd_journal_seek_tail(j
);
2705 return log_error_errno(r
, "Failed to seek to tail: %m");
2707 r
= sd_journal_previous(j
);
2709 } else if (arg_lines
>= 0) {
2710 r
= sd_journal_seek_tail(j
);
2712 return log_error_errno(r
, "Failed to seek to tail: %m");
2714 r
= sd_journal_previous_skip(j
, arg_lines
);
2716 } else if (arg_since_set
) {
2717 /* This is placed after arg_reverse and arg_lines. If --since is used without
2718 * both, we seek to the place of --since and search afterwards from there.
2719 * If used with --reverse or --lines, we seek to the tail first and check if
2720 * the entry is within the range of --since later. */
2722 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2724 return log_error_errno(r
, "Failed to seek to date: %m");
2725 since_seeked
= true;
2727 r
= sd_journal_next(j
);
2730 r
= sd_journal_seek_head(j
);
2732 return log_error_errno(r
, "Failed to seek to head: %m");
2734 r
= sd_journal_next(j
);
2737 return log_error_errno(r
, "Failed to iterate through journal: %m");
2742 pager_open(arg_pager_flags
);
2744 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2746 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2748 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2750 return log_error_errno(r
, "Failed to get cutoff: %m");
2753 printf("-- Journal begins at %s. --\n",
2754 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2756 printf("-- Journal begins at %s, ends at %s. --\n",
2757 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2758 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2764 .need_seek
= need_seek
,
2765 .since_seeked
= since_seeked
,
2769 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2772 assert(poll_fd
>= 0);
2774 r
= setup_event(&c
, poll_fd
, &e
);
2778 r
= sd_event_loop(e
);
2783 /* unref signal event sources. */
2784 e
= sd_event_unref(e
);
2786 r
= update_cursor(j
);
2790 /* re-send the original signal. */
2791 assert(SIGNAL_VALID(sig
));
2793 log_error("Failed to raise the original signal SIG%s, ignoring: %m", signal_to_string(sig
));
2803 if (n_shown
== 0 && !arg_quiet
)
2804 printf("-- No entries --\n");
2806 r
= update_cursor(j
);
2810 if (arg_compiled_pattern
&& n_shown
== 0)
2811 /* --grep was used, no error was thrown, but the pattern didn't
2812 * match anything. Let's mimic grep's behavior here and return
2813 * a non-zero exit code, so journalctl --grep can be used
2814 * in scripts and such */
2820 DEFINE_MAIN_FUNCTION(run
);