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 "memstream-util.h"
53 #include "missing_sched.h"
55 #include "mount-util.h"
56 #include "mountpoint-util.h"
57 #include "nulstr-util.h"
59 #include "parse-argument.h"
60 #include "parse-util.h"
61 #include "path-util.h"
62 #include "pcre2-util.h"
63 #include "pretty-print.h"
64 #include "qrcode-util.h"
65 #include "random-util.h"
66 #include "rlimit-util.h"
69 #include "signal-util.h"
70 #include "static-destruct.h"
71 #include "stdio-util.h"
72 #include "string-table.h"
74 #include "syslog-util.h"
75 #include "terminal-util.h"
76 #include "tmpfile-util.h"
77 #include "unit-name.h"
78 #include "user-util.h"
81 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
82 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
85 /* Special values for arg_lines */
86 ARG_LINES_DEFAULT
= -2,
90 static OutputMode arg_output
= OUTPUT_SHORT
;
91 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
92 static bool arg_utc
= false;
93 static bool arg_follow
= false;
94 static bool arg_full
= true;
95 static bool arg_all
= false;
96 static PagerFlags arg_pager_flags
= 0;
97 static int arg_lines
= ARG_LINES_DEFAULT
;
98 static bool arg_lines_oldest
= false;
99 static bool arg_no_tail
= false;
100 static bool arg_truncate_newline
= false;
101 static bool arg_quiet
= false;
102 static bool arg_merge
= false;
103 static bool arg_boot
= false;
104 static sd_id128_t arg_boot_id
= {};
105 static int arg_boot_offset
= 0;
106 static bool arg_dmesg
= false;
107 static bool arg_no_hostname
= false;
108 static const char *arg_cursor
= NULL
;
109 static const char *arg_cursor_file
= NULL
;
110 static const char *arg_after_cursor
= NULL
;
111 static bool arg_show_cursor
= false;
112 static const char *arg_directory
= NULL
;
113 static char **arg_file
= NULL
;
114 static bool arg_file_stdin
= false;
115 static int arg_priorities
= 0xFF;
116 static Set
*arg_facilities
= NULL
;
117 static char *arg_verify_key
= NULL
;
119 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
120 static bool arg_force
= false;
122 static usec_t arg_since
= 0, arg_until
= 0;
123 static bool arg_since_set
= false, arg_until_set
= false;
124 static char **arg_syslog_identifier
= NULL
;
125 static char **arg_system_units
= NULL
;
126 static char **arg_user_units
= NULL
;
127 static const char *arg_field
= NULL
;
128 static bool arg_catalog
= false;
129 static bool arg_reverse
= false;
130 static int arg_journal_type
= 0;
131 static int arg_namespace_flags
= 0;
132 static char *arg_root
= NULL
;
133 static char *arg_image
= NULL
;
134 static const char *arg_machine
= NULL
;
135 static const char *arg_namespace
= NULL
;
136 static uint64_t arg_vacuum_size
= 0;
137 static uint64_t arg_vacuum_n_files
= 0;
138 static usec_t arg_vacuum_time
= 0;
139 static Set
*arg_output_fields
= NULL
;
140 static const char *arg_pattern
= NULL
;
141 static pcre2_code
*arg_compiled_pattern
= NULL
;
142 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
143 ImagePolicy
*arg_image_policy
= NULL
;
145 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
148 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
151 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
152 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
153 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
154 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
155 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
166 ACTION_UPDATE_CATALOG
,
169 ACTION_RELINQUISH_VAR
,
173 ACTION_ROTATE_AND_VACUUM
,
175 ACTION_LIST_FIELD_NAMES
,
176 } arg_action
= ACTION_SHOW
;
178 typedef struct BootId
{
184 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
185 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
193 if (!path_startswith(devpath
, "/dev/"))
194 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
195 "Devpath does not start with /dev/");
197 if (stat(devpath
, &st
) < 0)
198 return log_error_errno(errno
, "Couldn't stat file: %m");
200 r
= sd_device_new_from_stat_rdev(&device
, &st
);
202 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
204 for (d
= device
; d
; ) {
205 _cleanup_free_
char *match
= NULL
;
206 const char *subsys
, *sysname
, *devnode
;
209 r
= sd_device_get_subsystem(d
, &subsys
);
213 r
= sd_device_get_sysname(d
, &sysname
);
217 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
221 r
= sd_journal_add_match(j
, match
, 0);
223 return log_error_errno(r
, "Failed to add match: %m");
225 if (sd_device_get_devname(d
, &devnode
) >= 0) {
226 _cleanup_free_
char *match1
= NULL
;
228 r
= stat(devnode
, &st
);
230 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
232 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
236 r
= sd_journal_add_match(j
, match1
, 0);
238 return log_error_errno(r
, "Failed to add match: %m");
242 if (sd_device_get_parent(d
, &parent
) < 0)
248 r
= add_match_this_boot(j
, arg_machine
);
250 return log_error_errno(r
, "Failed to add match for the current boot: %m");
255 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
258 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
260 return format_timestamp(buf
, l
, t
);
263 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
264 sd_id128_t id
= SD_ID128_NULL
;
267 if (streq(x
, "all")) {
268 *boot_id
= SD_ID128_NULL
;
271 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
274 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
275 r
= sd_id128_from_string(t
, &id
);
277 x
+= SD_ID128_STRING_MAX
- 1;
279 if (!IN_SET(*x
, 0, '-', '+'))
283 r
= safe_atoi(x
, &off
);
288 r
= safe_atoi(x
, &off
);
302 static int parse_lines(const char *arg
, bool graceful
) {
306 assert(arg
|| graceful
);
311 if (streq(arg
, "all")) {
312 arg_lines
= ARG_LINES_ALL
;
316 l
= startswith(arg
, "+");
318 r
= safe_atoi(l
?: arg
, &n
);
319 if (r
< 0 || n
< 0) {
323 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse --lines='%s'.", arg
);
327 arg_lines_oldest
= !!l
;
333 arg_lines_oldest
= false;
337 static bool arg_lines_needs_seek_end(void) {
338 return arg_lines
>= 0 && !arg_lines_oldest
;
341 static int help_facilities(void) {
343 puts("Available facilities:");
345 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
346 _cleanup_free_
char *t
= NULL
;
348 if (log_facility_unshifted_to_string_alloc(i
, &t
))
356 static int help(void) {
357 _cleanup_free_
char *link
= NULL
;
360 pager_open(arg_pager_flags
);
362 r
= terminal_urlify_man("journalctl", "1", &link
);
366 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
367 "%5$sQuery the journal.%6$s\n\n"
368 "%3$sSource Options:%4$s\n"
369 " --system Show the system journal\n"
370 " --user Show the user journal for the current user\n"
371 " -M --machine=CONTAINER Operate on local container\n"
372 " -m --merge Show entries from all available journals\n"
373 " -D --directory=PATH Show journal files from directory\n"
374 " --file=PATH Show journal file\n"
375 " --root=PATH Operate on an alternate filesystem root\n"
376 " --image=PATH Operate on disk image as filesystem root\n"
377 " --image-policy=POLICY Specify disk image dissection policy\n"
378 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
379 "\n%3$sFiltering Options:%4$s\n"
380 " -S --since=DATE Show entries not older than the specified date\n"
381 " -U --until=DATE Show entries not newer than the specified date\n"
382 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
383 " --after-cursor=CURSOR Show entries after the specified cursor\n"
384 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
385 " -b --boot[=ID] Show current boot or the specified boot\n"
386 " -u --unit=UNIT Show logs from the specified unit\n"
387 " --user-unit=UNIT Show logs from the specified user unit\n"
388 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
389 " -p --priority=RANGE Show entries with the specified priority\n"
390 " --facility=FACILITY... Show entries with the specified facilities\n"
391 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
392 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
393 " -k --dmesg Show kernel message log from the current boot\n"
394 "\n%3$sOutput Control Options:%4$s\n"
395 " -o --output=STRING Change journal output mode (short, short-precise,\n"
396 " short-iso, short-iso-precise, short-full,\n"
397 " short-monotonic, short-unix, verbose, export,\n"
398 " json, json-pretty, json-sse, json-seq, cat,\n"
400 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
401 " -n --lines[=[+]INTEGER] Number of journal entries to show\n"
402 " -r --reverse Show the newest entries first\n"
403 " --show-cursor Print the cursor after all the entries\n"
404 " --utc Express time in Coordinated Universal Time (UTC)\n"
405 " -x --catalog Add message explanations where available\n"
406 " --no-hostname Suppress output of hostname field\n"
407 " --no-full Ellipsize fields\n"
408 " -a --all Show all fields, including long and unprintable\n"
409 " -f --follow Follow the journal\n"
410 " --no-tail Show all lines, even in follow mode\n"
411 " --truncate-newline Truncate entries by first newline character\n"
412 " -q --quiet Do not show info messages and privilege warning\n"
413 "\n%3$sPager Control Options:%4$s\n"
414 " --no-pager Do not pipe output into a pager\n"
415 " -e --pager-end Immediately jump to the end in the pager\n"
416 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
417 " --interval=TIME Time interval for changing the FSS sealing key\n"
418 " --verify-key=KEY Specify FSS verification key\n"
419 " --force Override of the FSS key pair with --setup-keys\n"
420 "\n%3$sCommands:%4$s\n"
421 " -h --help Show this help text\n"
422 " --version Show package version\n"
423 " -N --fields List all field names currently used\n"
424 " -F --field=FIELD List all values that a specified field takes\n"
425 " --list-boots Show terse information about recorded boots\n"
426 " --disk-usage Show total disk usage of all journal files\n"
427 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
428 " --vacuum-files=INT Leave only the specified number of journal files\n"
429 " --vacuum-time=TIME Remove journal files older than specified time\n"
430 " --verify Verify journal file consistency\n"
431 " --sync Synchronize unwritten journal messages to disk\n"
432 " --relinquish-var Stop logging to disk, log to temporary file system\n"
433 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
434 " --flush Flush all journal data from /run into /var\n"
435 " --rotate Request immediate rotation of the journal files\n"
436 " --header Show journal header information\n"
437 " --list-catalog Show all message IDs in the catalog\n"
438 " --dump-catalog Show entries in the message catalog\n"
439 " --update-catalog Update the message catalog database\n"
440 " --setup-keys Generate a new FSS key pair\n"
441 "\nSee the %2$s for details.\n",
442 program_invocation_short_name
,
452 static int parse_argv(int argc
, char *argv
[]) {
488 ARG_SMART_RELINQUISH_VAR
,
490 ARG_TRUNCATE_NEWLINE
,
499 static const struct option options
[] = {
500 { "help", no_argument
, NULL
, 'h' },
501 { "version" , no_argument
, NULL
, ARG_VERSION
},
502 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
503 { "pager-end", no_argument
, NULL
, 'e' },
504 { "follow", no_argument
, NULL
, 'f' },
505 { "force", no_argument
, NULL
, ARG_FORCE
},
506 { "output", required_argument
, NULL
, 'o' },
507 { "all", no_argument
, NULL
, 'a' },
508 { "full", no_argument
, NULL
, 'l' },
509 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
510 { "lines", optional_argument
, NULL
, 'n' },
511 { "truncate-newline", no_argument
, NULL
, ARG_TRUNCATE_NEWLINE
},
512 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
513 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
514 { "quiet", no_argument
, NULL
, 'q' },
515 { "merge", no_argument
, NULL
, 'm' },
516 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
517 { "boot", optional_argument
, NULL
, 'b' },
518 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
519 { "dmesg", no_argument
, NULL
, 'k' },
520 { "system", no_argument
, NULL
, ARG_SYSTEM
},
521 { "user", no_argument
, NULL
, ARG_USER
},
522 { "directory", required_argument
, NULL
, 'D' },
523 { "file", required_argument
, NULL
, ARG_FILE
},
524 { "root", required_argument
, NULL
, ARG_ROOT
},
525 { "image", required_argument
, NULL
, ARG_IMAGE
},
526 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
527 { "header", no_argument
, NULL
, ARG_HEADER
},
528 { "identifier", required_argument
, NULL
, 't' },
529 { "priority", required_argument
, NULL
, 'p' },
530 { "facility", required_argument
, NULL
, ARG_FACILITY
},
531 { "grep", required_argument
, NULL
, 'g' },
532 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
533 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
534 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
535 { "verify", no_argument
, NULL
, ARG_VERIFY
},
536 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
537 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
538 { "cursor", required_argument
, NULL
, 'c' },
539 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
540 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
541 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
542 { "since", required_argument
, NULL
, 'S' },
543 { "until", required_argument
, NULL
, 'U' },
544 { "unit", required_argument
, NULL
, 'u' },
545 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
546 { "field", required_argument
, NULL
, 'F' },
547 { "fields", no_argument
, NULL
, 'N' },
548 { "catalog", no_argument
, NULL
, 'x' },
549 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
550 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
551 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
552 { "reverse", no_argument
, NULL
, 'r' },
553 { "machine", required_argument
, NULL
, 'M' },
554 { "utc", no_argument
, NULL
, ARG_UTC
},
555 { "flush", no_argument
, NULL
, ARG_FLUSH
},
556 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
557 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
558 { "sync", no_argument
, NULL
, ARG_SYNC
},
559 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
560 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
561 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
562 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
563 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
564 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
565 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
574 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
585 arg_pager_flags
|= PAGER_DISABLE
;
589 arg_pager_flags
|= PAGER_JUMP_TO_END
;
591 if (arg_lines
== ARG_LINES_DEFAULT
)
603 if (streq(optarg
, "help")) {
604 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
608 arg_output
= output_mode_from_string(optarg
);
610 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
612 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
615 if (OUTPUT_MODE_IS_JSON(arg_output
))
616 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
618 arg_json_format_flags
= JSON_FORMAT_OFF
;
635 r
= parse_lines(optarg
?: argv
[optind
], !optarg
);
638 if (r
> 0 && !optarg
)
647 case ARG_TRUNCATE_NEWLINE
:
648 arg_truncate_newline
= true;
652 arg_action
= ACTION_NEW_ID128
;
665 arg_boot_id
= SD_ID128_NULL
;
671 arg_boot_id
= SD_ID128_NULL
;
675 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
677 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
681 /* Hmm, no argument? Maybe the next
682 * word on the command line is
683 * supposed to be the argument? Let's
684 * see if there is one and is parsable
685 * as a boot descriptor... */
686 } else if (optind
< argc
) {
687 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
696 arg_action
= ACTION_LIST_BOOTS
;
700 arg_boot
= arg_dmesg
= true;
704 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
708 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
712 arg_machine
= optarg
;
716 if (streq(optarg
, "*")) {
717 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
718 arg_namespace
= NULL
;
719 } else if (startswith(optarg
, "+")) {
720 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
721 arg_namespace
= optarg
+ 1;
722 } else if (isempty(optarg
)) {
723 arg_namespace_flags
= 0;
724 arg_namespace
= NULL
;
726 arg_namespace_flags
= 0;
727 arg_namespace
= optarg
;
733 arg_directory
= optarg
;
737 if (streq(optarg
, "-"))
738 /* An undocumented feature: we can read journal files from STDIN. We don't document
739 * this though, since after all we only support this for mmap-able, seekable files, and
740 * not for example pipes which are probably the primary usecase for reading things from
741 * STDIN. To avoid confusion we hence don't document this feature. */
742 arg_file_stdin
= true;
744 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
746 return log_error_errno(r
, "Failed to add paths: %m");
751 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
757 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
762 case ARG_IMAGE_POLICY
:
763 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
772 case ARG_CURSOR_FILE
:
773 arg_cursor_file
= optarg
;
776 case ARG_AFTER_CURSOR
:
777 arg_after_cursor
= optarg
;
780 case ARG_SHOW_CURSOR
:
781 arg_show_cursor
= true;
785 arg_action
= ACTION_PRINT_HEADER
;
789 arg_action
= ACTION_VERIFY
;
793 arg_action
= ACTION_DISK_USAGE
;
796 case ARG_VACUUM_SIZE
:
797 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
799 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
801 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
804 case ARG_VACUUM_FILES
:
805 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
807 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
809 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
812 case ARG_VACUUM_TIME
:
813 r
= parse_sec(optarg
, &arg_vacuum_time
);
815 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
817 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
826 arg_action
= ACTION_SETUP_KEYS
;
830 r
= free_and_strdup(&arg_verify_key
, optarg
);
833 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
834 * in ps or htop output. */
835 memset(optarg
, 'x', strlen(optarg
));
837 arg_action
= ACTION_VERIFY
;
842 r
= parse_sec(optarg
, &arg_interval
);
843 if (r
< 0 || arg_interval
<= 0)
844 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
845 "Failed to parse sealing key change interval: %s", optarg
);
852 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
853 "Compiled without forward-secure sealing support.");
859 dots
= strstr(optarg
, "..");
861 _cleanup_free_
char *a
= NULL
;
865 a
= strndup(optarg
, dots
- optarg
);
869 from
= log_level_from_string(a
);
870 to
= log_level_from_string(dots
+ 2);
872 if (from
< 0 || to
< 0)
873 return log_error_errno(from
< 0 ? from
: to
,
874 "Failed to parse log level range %s", optarg
);
879 for (i
= from
; i
<= to
; i
++)
880 arg_priorities
|= 1 << i
;
882 for (i
= to
; i
<= from
; i
++)
883 arg_priorities
|= 1 << i
;
889 p
= log_level_from_string(optarg
);
891 return log_error_errno(p
, "Unknown log level %s", optarg
);
895 for (i
= 0; i
<= p
; i
++)
896 arg_priorities
|= 1 << i
;
906 _cleanup_free_
char *fac
= NULL
;
909 r
= extract_first_word(&p
, &fac
, ",", 0);
911 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
915 if (streq(fac
, "help")) {
920 num
= log_facility_unshifted_from_string(fac
);
922 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
924 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
932 arg_pattern
= optarg
;
935 case ARG_CASE_SENSITIVE
:
937 r
= parse_boolean(optarg
);
939 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
940 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
942 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
947 r
= parse_timestamp(optarg
, &arg_since
);
949 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
950 "Failed to parse timestamp: %s", optarg
);
951 arg_since_set
= true;
955 r
= parse_timestamp(optarg
, &arg_until
);
957 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
958 "Failed to parse timestamp: %s", optarg
);
959 arg_until_set
= true;
963 r
= strv_extend(&arg_syslog_identifier
, optarg
);
969 r
= strv_extend(&arg_system_units
, optarg
);
975 r
= strv_extend(&arg_user_units
, optarg
);
981 arg_action
= ACTION_LIST_FIELDS
;
986 arg_action
= ACTION_LIST_FIELD_NAMES
;
989 case ARG_NO_HOSTNAME
:
990 arg_no_hostname
= true;
997 case ARG_LIST_CATALOG
:
998 arg_action
= ACTION_LIST_CATALOG
;
1001 case ARG_DUMP_CATALOG
:
1002 arg_action
= ACTION_DUMP_CATALOG
;
1005 case ARG_UPDATE_CATALOG
:
1006 arg_action
= ACTION_UPDATE_CATALOG
;
1018 arg_action
= ACTION_FLUSH
;
1021 case ARG_SMART_RELINQUISH_VAR
: {
1022 int root_mnt_id
, log_mnt_id
;
1024 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
1025 * if it's on the same mount as the root file system there's no point in
1026 * relinquishing access and we can leave journald write to it until the very last
1029 r
= path_get_mnt_id("/", &root_mnt_id
);
1031 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1033 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1035 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1036 else if (root_mnt_id
== log_mnt_id
) {
1037 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1040 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1046 case ARG_RELINQUISH_VAR
:
1047 arg_action
= ACTION_RELINQUISH_VAR
;
1051 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1055 arg_action
= ACTION_SYNC
;
1058 case ARG_OUTPUT_FIELDS
: {
1059 _cleanup_strv_free_
char **v
= NULL
;
1061 v
= strv_split(optarg
, ",");
1065 r
= set_put_strdupv(&arg_output_fields
, v
);
1075 assert_not_reached();
1079 arg_lines
= ARG_LINES_ALL
;
1081 if (arg_follow
&& !arg_since_set
&& arg_lines
== ARG_LINES_DEFAULT
)
1084 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1086 arg_boot_id
= SD_ID128_NULL
;
1087 arg_boot_offset
= 0;
1090 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1091 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1092 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1094 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1095 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1096 "--since= must be before --until=.");
1098 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1099 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1100 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1102 if (arg_follow
&& arg_reverse
)
1103 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1104 "Please specify either --reverse or --follow, not both.");
1106 if (arg_lines
>= 0 && arg_lines_oldest
&& (arg_reverse
|| arg_follow
))
1107 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1108 "--lines=+N is unsupported when --reverse or --follow is specified.");
1110 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1111 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1112 "Extraneous arguments starting with '%s'",
1115 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1116 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1117 "Using --boot or --list-boots with --merge is not supported.");
1119 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1120 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1121 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1122 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1123 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1127 arg_system_units
= strv_free(arg_system_units
);
1131 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1135 /* When --grep is used along with --lines without '+', i.e. when we start from the end of the
1136 * journal, we don't know how many lines we can print. So we search backwards and count until
1137 * enough lines have been printed or we hit the head.
1138 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1139 * if that is specified. */
1140 if (arg_lines_needs_seek_end() && !arg_follow
)
1147 static int add_matches(sd_journal
*j
, char **args
) {
1148 bool have_term
= false;
1152 STRV_FOREACH(i
, args
) {
1155 if (streq(*i
, "+")) {
1158 r
= sd_journal_add_disjunction(j
);
1161 } else if (path_is_absolute(*i
)) {
1162 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1165 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1167 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1169 if (lstat(p
, &st
) < 0)
1170 return log_error_errno(errno
, "Couldn't stat file: %m");
1172 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1173 if (executable_is_script(p
, &interpreter
) > 0) {
1174 _cleanup_free_
char *comm
= NULL
;
1176 r
= path_extract_filename(p
, &comm
);
1178 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1180 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1184 /* Append _EXE only if the interpreter is not a link.
1185 Otherwise, it might be outdated often. */
1186 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1187 t2
= strjoin("_EXE=", interpreter
);
1192 t
= strjoin("_EXE=", p
);
1197 r
= sd_journal_add_match(j
, t
, 0);
1200 r
= sd_journal_add_match(j
, t2
, 0);
1202 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1203 r
= add_matches_for_device(j
, p
);
1207 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1208 "File is neither a device node, nor regular file, nor executable: %s",
1213 r
= sd_journal_add_match(j
, *i
, 0);
1218 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1221 if (!strv_isempty(args
) && !have_term
)
1222 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1223 "\"+\" can only be used between terms");
1228 static int discover_next_boot(
1230 sd_id128_t previous_boot_id
,
1240 /* We expect the journal to be on the last position of a boot
1241 * (in relation to the direction we are going), so that the next
1242 * invocation of sd_journal_next/previous will be from a different
1243 * boot. We then collect any information we desire and then jump
1244 * to the last location of the new boot by using a _BOOT_ID match
1245 * coming from the other journal direction. */
1247 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1248 * we can actually advance to a *different* boot. */
1249 sd_journal_flush_matches(j
);
1253 r
= sd_journal_previous(j
);
1255 r
= sd_journal_next(j
);
1260 return 0; /* End of journal, yay. */
1263 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot
.id
);
1267 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1268 * normally, this will only require a single iteration, as we moved to the last entry of the previous
1269 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1270 * complete than the main entry array, and hence might reference an entry that's not actually the last
1271 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1272 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1275 } while (sd_id128_equal(boot
.id
, previous_boot_id
));
1277 r
= sd_journal_get_realtime_usec(j
, &boot
.first_usec
);
1281 /* Now seek to the last occurrence of this boot ID. */
1282 r
= add_match_boot_id(j
, boot
.id
);
1287 r
= sd_journal_seek_head(j
);
1289 r
= sd_journal_seek_tail(j
);
1294 r
= sd_journal_next(j
);
1296 r
= sd_journal_previous(j
);
1300 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1301 "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. */
1303 r
= sd_journal_get_realtime_usec(j
, &boot
.last_usec
);
1307 sd_journal_flush_matches(j
);
1312 static int find_boot_by_id(sd_journal
*j
) {
1317 sd_journal_flush_matches(j
);
1319 r
= add_match_boot_id(j
, arg_boot_id
);
1323 r
= sd_journal_seek_head(j
); /* seek to oldest */
1327 r
= sd_journal_next(j
); /* read the oldest entry */
1331 /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID.
1332 * After flushing the matches, one more invocation of _previous() will hence place us at the
1333 * following entry, which must then have an older boot ID */
1335 sd_journal_flush_matches(j
);
1339 static int find_boot_by_offset(sd_journal
*j
) {
1340 bool advance_older
, skip_once
;
1343 /* Adjust for the asymmetry that offset 0 is the last (and current) boot, while 1 is considered the
1344 * (chronological) first boot in the journal. */
1345 advance_older
= skip_once
= arg_boot_offset
<= 0;
1348 r
= sd_journal_seek_tail(j
); /* seek to newest */
1350 r
= sd_journal_seek_head(j
); /* seek to oldest */
1354 /* No sd_journal_next()/_previous() here.
1356 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1357 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1360 int offset
= arg_boot_offset
;
1361 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1365 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, &boot
);
1369 previous_boot_id
= boot
.id
;
1372 offset
+= advance_older
? 1 : -1;
1376 arg_boot_id
= boot
.id
;
1382 static int get_boots(sd_journal
*j
, BootId
**ret_boots
, size_t *ret_n_boots
) {
1383 _cleanup_free_ BootId
*boots
= NULL
;
1389 assert(ret_n_boots
);
1391 r
= sd_journal_seek_head(j
); /* seek to oldest */
1395 /* No sd_journal_next()/_previous() here.
1397 * At this point the read pointer is positioned before the oldest entry in the whole journal. The
1398 * next invocation of _next() will hence position us at the oldest entry we have. */
1400 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1404 r
= discover_next_boot(j
, previous_boot_id
, /* advance_older = */ false, &boot
);
1410 previous_boot_id
= boot
.id
;
1412 FOREACH_ARRAY(i
, boots
, n_boots
)
1413 if (sd_id128_equal(i
->id
, boot
.id
))
1414 /* The boot id is already stored, something wrong with the journal files.
1415 * Exiting as otherwise this problem would cause an infinite loop. */
1418 if (!GREEDY_REALLOC(boots
, n_boots
+ 1))
1421 boots
[n_boots
++] = boot
;
1424 *ret_boots
= TAKE_PTR(boots
);
1425 *ret_n_boots
= n_boots
;
1429 static int list_boots(sd_journal
*j
) {
1430 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1431 _cleanup_free_ BootId
*boots
= NULL
;
1437 r
= get_boots(j
, &boots
, &n_boots
);
1439 return log_error_errno(r
, "Failed to determine boots: %m");
1443 table
= table_new("idx", "boot id", "first entry", "last entry");
1448 table_set_width(table
, 0);
1450 r
= table_set_json_field_name(table
, 0, "index");
1452 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1454 (void) table_set_sort(table
, (size_t) 0);
1455 (void) table_set_reverse(table
, 0, arg_reverse
);
1457 FOREACH_ARRAY(i
, boots
, n_boots
) {
1458 r
= table_add_many(table
,
1459 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1460 TABLE_SET_ALIGN_PERCENT
, 100,
1462 TABLE_TIMESTAMP
, i
->first_usec
,
1463 TABLE_TIMESTAMP
, i
->last_usec
);
1465 return table_log_add_error(r
);
1468 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1470 return table_log_print_error(r
);
1475 static int add_boot(sd_journal
*j
) {
1483 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1484 * We can do this only when we logs are coming from the current machine,
1485 * so take the slow path if log location is specified. */
1486 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1487 !arg_directory
&& !arg_file
&& !arg_root
)
1488 return add_match_this_boot(j
, arg_machine
);
1490 if (sd_id128_is_null(arg_boot_id
)) {
1491 r
= find_boot_by_offset(j
);
1493 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1496 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1497 "No journal boot entry found from the specified boot offset (%+i).",
1500 r
= find_boot_by_id(j
);
1502 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1503 SD_ID128_TO_STRING(arg_boot_id
));
1505 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1506 "No journal boot entry found from the specified boot ID (%s).",
1507 SD_ID128_TO_STRING(arg_boot_id
));
1510 r
= add_match_boot_id(j
, arg_boot_id
);
1512 return log_error_errno(r
, "Failed to add match: %m");
1514 r
= sd_journal_add_conjunction(j
);
1516 return log_error_errno(r
, "Failed to add conjunction: %m");
1521 static int add_dmesg(sd_journal
*j
) {
1528 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1529 STRLEN("_TRANSPORT=kernel"));
1531 return log_error_errno(r
, "Failed to add match: %m");
1533 r
= sd_journal_add_conjunction(j
);
1535 return log_error_errno(r
, "Failed to add conjunction: %m");
1540 static int get_possible_units(
1546 _cleanup_set_free_free_ Set
*found
= NULL
;
1549 found
= set_new(&string_hash_ops
);
1553 NULSTR_FOREACH(field
, fields
) {
1557 r
= sd_journal_query_unique(j
, field
);
1561 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1564 _cleanup_free_
char *u
= NULL
;
1566 eq
= memchr(data
, '=', size
);
1568 prefix
= eq
- (char*) data
+ 1;
1572 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1576 STRV_FOREACH(pattern
, patterns
)
1577 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1578 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1580 r
= set_consume(found
, u
);
1582 if (r
< 0 && r
!= -EEXIST
)
1590 *units
= TAKE_PTR(found
);
1595 /* This list is supposed to return the superset of unit names
1596 * possibly matched by rules added with add_matches_for_unit... */
1597 #define SYSTEM_UNITS \
1601 "OBJECT_SYSTEMD_UNIT\0" \
1604 /* ... and add_matches_for_user_unit */
1605 #define USER_UNITS \
1606 "_SYSTEMD_USER_UNIT\0" \
1608 "COREDUMP_USER_UNIT\0" \
1609 "OBJECT_SYSTEMD_USER_UNIT\0" \
1610 "_SYSTEMD_USER_SLICE\0"
1612 static int add_units(sd_journal
*j
) {
1613 _cleanup_strv_free_
char **patterns
= NULL
;
1618 STRV_FOREACH(i
, arg_system_units
) {
1619 _cleanup_free_
char *u
= NULL
;
1621 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1625 if (string_is_glob(u
)) {
1626 r
= strv_push(&patterns
, u
);
1631 r
= add_matches_for_unit(j
, u
);
1634 r
= sd_journal_add_disjunction(j
);
1641 if (!strv_isempty(patterns
)) {
1642 _cleanup_set_free_free_ Set
*units
= NULL
;
1645 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1649 SET_FOREACH(u
, units
) {
1650 r
= add_matches_for_unit(j
, u
);
1653 r
= sd_journal_add_disjunction(j
);
1660 patterns
= strv_free(patterns
);
1662 STRV_FOREACH(i
, arg_user_units
) {
1663 _cleanup_free_
char *u
= NULL
;
1665 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1669 if (string_is_glob(u
)) {
1670 r
= strv_push(&patterns
, u
);
1675 r
= add_matches_for_user_unit(j
, u
, getuid());
1678 r
= sd_journal_add_disjunction(j
);
1685 if (!strv_isempty(patterns
)) {
1686 _cleanup_set_free_free_ Set
*units
= NULL
;
1689 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1693 SET_FOREACH(u
, units
) {
1694 r
= add_matches_for_user_unit(j
, u
, getuid());
1697 r
= sd_journal_add_disjunction(j
);
1704 /* Complain if the user request matches but nothing whatsoever was
1705 * found, since otherwise everything would be matched. */
1706 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1709 r
= sd_journal_add_conjunction(j
);
1716 static int add_priorities(sd_journal
*j
) {
1717 char match
[] = "PRIORITY=0";
1721 if (arg_priorities
== 0xFF)
1724 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1725 if (arg_priorities
& (1 << i
)) {
1726 match
[sizeof(match
)-2] = '0' + i
;
1728 r
= sd_journal_add_match(j
, match
, strlen(match
));
1730 return log_error_errno(r
, "Failed to add match: %m");
1733 r
= sd_journal_add_conjunction(j
);
1735 return log_error_errno(r
, "Failed to add conjunction: %m");
1740 static int add_facilities(sd_journal
*j
) {
1744 SET_FOREACH(p
, arg_facilities
) {
1745 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1747 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1749 r
= sd_journal_add_match(j
, match
, strlen(match
));
1751 return log_error_errno(r
, "Failed to add match: %m");
1757 static int add_syslog_identifier(sd_journal
*j
) {
1762 STRV_FOREACH(i
, arg_syslog_identifier
) {
1763 _cleanup_free_
char *u
= NULL
;
1765 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1768 r
= sd_journal_add_match(j
, u
, 0);
1771 r
= sd_journal_add_disjunction(j
);
1776 r
= sd_journal_add_conjunction(j
);
1784 static int format_journal_url(
1794 _cleanup_(memstream_done
) MemStream m
= {};
1798 assert(seed_size
> 0);
1800 f
= memstream_init(&m
);
1807 for (size_t i
= 0; i
< seed_size
; i
++) {
1808 if (i
> 0 && i
% 3 == 0)
1810 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1813 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1816 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1818 fprintf(f
, ";hostname=%s", hn
);
1821 return memstream_finalize(&m
, ret_url
, NULL
);
1825 static int setup_keys(void) {
1827 size_t mpk_size
, seed_size
, state_size
;
1828 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1829 _cleanup_free_
char *p
= NULL
;
1830 uint8_t *mpk
, *seed
, *state
;
1831 _cleanup_close_
int fd
= -EBADF
;
1832 sd_id128_t machine
, boot
;
1837 r
= stat("/var/log/journal", &st
);
1838 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1839 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1841 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1842 log_error("%s is not a directory, must be using persistent logging for FSS.",
1843 "/var/log/journal");
1844 return r
< 0 ? -errno
: -ENOTDIR
;
1847 r
= sd_id128_get_machine(&machine
);
1849 return log_error_errno(r
, "Failed to get machine ID: %m");
1851 r
= sd_id128_get_boot(&boot
);
1853 return log_error_errno(r
, "Failed to get boot ID: %m");
1855 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1856 SD_ID128_FORMAT_VAL(machine
)) < 0)
1861 if (r
< 0 && errno
!= ENOENT
)
1862 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1863 } else if (access(p
, F_OK
) >= 0)
1864 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1865 "Sealing key file %s exists already. Use --force to recreate.", p
);
1867 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1868 SD_ID128_FORMAT_VAL(machine
)) < 0)
1871 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1872 mpk
= alloca_safe(mpk_size
);
1874 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1875 seed
= alloca_safe(seed_size
);
1877 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1878 state
= alloca_safe(state_size
);
1880 log_info("Generating seed...");
1881 r
= crypto_random_bytes(seed
, seed_size
);
1883 return log_error_errno(r
, "Failed to acquire random seed: %m");
1885 log_info("Generating key pair...");
1886 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1888 log_info("Generating sealing key...");
1889 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1891 assert(arg_interval
> 0);
1893 n
= now(CLOCK_REALTIME
);
1897 fd
= mkostemp_safe(k
);
1899 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1901 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1903 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1904 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1906 struct FSSHeader h
= {
1907 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1908 .machine_id
= machine
,
1910 .header_size
= htole64(sizeof(h
)),
1911 .start_usec
= htole64(n
* arg_interval
),
1912 .interval_usec
= htole64(arg_interval
),
1913 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1914 .fsprg_state_size
= htole64(state_size
),
1917 r
= loop_write(fd
, &h
, sizeof(h
), false);
1919 return log_error_errno(r
, "Failed to write header: %m");
1921 r
= loop_write(fd
, state
, state_size
, false);
1923 return log_error_errno(r
, "Failed to write state: %m");
1925 if (rename(k
, p
) < 0)
1926 return log_error_errno(errno
, "Failed to link file: %m");
1930 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1932 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1937 hn
= gethostname_malloc();
1939 hostname_cleanup(hn
);
1942 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1944 "The %ssecret sealing key%s has been written to the following local file.\n"
1945 "This key file is automatically updated when the sealing key is advanced.\n"
1946 "It should not be used on multiple hosts.\n"
1950 "The sealing key is automatically changed every %s.\n"
1952 "Please write down the following %ssecret verification key%s. It should be stored\n"
1953 "in a safe location and should not be saved locally on disk.\n"
1955 strempty(hn
), hn
? "/" : "",
1956 SD_ID128_FORMAT_VAL(machine
),
1957 ansi_highlight(), ansi_normal(),
1959 FORMAT_TIMESPAN(arg_interval
, 0),
1960 ansi_highlight(), ansi_normal(),
1961 ansi_highlight_red());
1968 fprintf(stderr
, "%s", ansi_normal());
1970 _cleanup_free_
char *url
= NULL
;
1971 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1975 (void) print_qrcode(stderr
,
1976 "To transfer the verification key to your phone scan the QR code below",
1983 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1984 "Forward-secure sealing not available.");
1988 static int verify(sd_journal
*j
, bool verbose
) {
1994 log_show_color(true);
1996 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1998 usec_t first
= 0, validated
= 0, last
= 0;
2001 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
2002 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
2005 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
2007 /* If the key was invalid give up right-away. */
2010 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
2012 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
2013 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
2015 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
2016 if (validated
> 0) {
2017 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2018 "=> Validated from %s to %s, final %s entries not sealed.",
2019 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
2020 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
2021 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
2022 } else if (last
> 0)
2023 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2024 "=> No sealing yet, %s of entries not sealed.",
2025 FORMAT_TIMESPAN(last
- first
, 0));
2027 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2028 "=> No sealing yet, no entries in file.");
2036 static int simple_varlink_call(const char *option
, const char *method
) {
2037 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2038 const char *error
, *fn
;
2042 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2044 fn
= arg_namespace
?
2045 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2046 "/run/systemd/journal/io.systemd.journal";
2048 r
= varlink_connect_address(&link
, fn
);
2050 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2052 (void) varlink_set_description(link
, "journal");
2053 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2055 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2057 return log_error_errno(r
, "Failed to execute varlink call: %m");
2059 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2060 "Failed to execute varlink call: %s", error
);
2065 static int flush_to_var(void) {
2066 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2067 return 0; /* Already flushed, no need to contact journald */
2068 if (errno
!= ENOENT
)
2069 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2071 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2074 static int relinquish_var(void) {
2075 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2078 static int rotate(void) {
2079 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2082 static int sync_journal(void) {
2083 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2086 static int action_list_fields(sd_journal
*j
) {
2093 r
= sd_journal_set_data_threshold(j
, 0);
2095 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2097 r
= sd_journal_query_unique(j
, arg_field
);
2099 return log_error_errno(r
, "Failed to query unique data objects: %m");
2101 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2104 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2107 eq
= memchr(data
, '=', size
);
2109 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2111 printf("%.*s\n", (int) size
, (const char*) data
);
2119 static int update_cursor(sd_journal
*j
) {
2120 _cleanup_free_
char *cursor
= NULL
;
2125 if (!arg_show_cursor
&& !arg_cursor_file
)
2128 r
= sd_journal_get_cursor(j
, &cursor
);
2129 if (r
== -EADDRNOTAVAIL
)
2132 return log_error_errno(r
, "Failed to get cursor: %m");
2134 if (arg_show_cursor
)
2135 printf("-- cursor: %s\n", cursor
);
2137 if (arg_cursor_file
) {
2138 r
= write_string_file(arg_cursor_file
, cursor
, WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_ATOMIC
);
2140 return log_error_errno(r
, "Failed to write new cursor to %s: %m", arg_cursor_file
);
2146 typedef struct Context
{
2147 sd_journal
*journal
;
2151 bool previous_boot_id_valid
;
2152 sd_id128_t previous_boot_id
;
2153 sd_id128_t previous_boot_id_output
;
2154 dual_timestamp previous_ts_output
;
2157 static int show(Context
*c
) {
2163 j
= ASSERT_PTR(c
->journal
);
2165 while (arg_lines
< 0 || n_shown
< arg_lines
|| arg_follow
) {
2167 size_t highlight
[2] = {};
2170 r
= sd_journal_step_one(j
, !arg_reverse
);
2172 return log_error_errno(r
, "Failed to iterate through journal: %m");
2177 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2178 /* If --lines= is set, we usually rely on the n_shown to tell us
2179 * when to stop. However, if --since= is set too, we may end up
2180 * having less than --lines= to output. In this case let's also
2181 * check if the entry is in range. */
2185 r
= sd_journal_get_realtime_usec(j
, &usec
);
2187 return log_error_errno(r
, "Failed to determine timestamp: %m");
2188 if (usec
> arg_until
)
2192 if (arg_since_set
&& (arg_reverse
|| !c
->since_seeked
)) {
2195 r
= sd_journal_get_realtime_usec(j
, &usec
);
2197 return log_error_errno(r
, "Failed to determine timestamp: %m");
2199 if (usec
< arg_since
) {
2201 break; /* Reached the earliest entry */
2203 /* arg_lines >= 0 (!since_seeked):
2204 * We jumped arg_lines back and it seems to be too much */
2205 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2207 return log_error_errno(r
, "Failed to seek to date: %m");
2208 c
->since_seeked
= true;
2210 c
->need_seek
= true;
2213 c
->since_seeked
= true; /* We're surely within the range of --since now */
2216 if (!arg_merge
&& !arg_quiet
) {
2219 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2221 if (c
->previous_boot_id_valid
&&
2222 !sd_id128_equal(boot_id
, c
->previous_boot_id
))
2223 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2224 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2226 c
->previous_boot_id
= boot_id
;
2227 c
->previous_boot_id_valid
= true;
2231 if (arg_compiled_pattern
) {
2232 const void *message
;
2235 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2238 c
->need_seek
= true;
2242 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2245 assert_se(message
= startswith(message
, "MESSAGE="));
2247 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2248 len
- strlen("MESSAGE="), highlight
);
2252 c
->need_seek
= true;
2258 arg_all
* OUTPUT_SHOW_ALL
|
2259 arg_full
* OUTPUT_FULL_WIDTH
|
2260 colors_enabled() * OUTPUT_COLOR
|
2261 arg_catalog
* OUTPUT_CATALOG
|
2262 arg_utc
* OUTPUT_UTC
|
2263 arg_truncate_newline
* OUTPUT_TRUNCATE_NEWLINE
|
2264 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2266 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2267 arg_output_fields
, highlight
, &c
->ellipsized
,
2268 &c
->previous_ts_output
, &c
->previous_boot_id_output
);
2269 c
->need_seek
= true;
2270 if (r
== -EADDRNOTAVAIL
)
2277 /* If journalctl take a long time to process messages, and during that time journal file
2278 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2279 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2280 * in the "following" case. By periodically calling sd_journal_process() during the processing
2281 * loop we shrink the window of time a client instance has open file descriptors for rotated
2282 * (deleted) journal files. */
2283 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2284 r
= sd_journal_process(j
);
2286 return log_error_errno(r
, "Failed to process inotify events: %m");
2293 static int show_and_fflush(Context
*c
, sd_event_source
*s
) {
2301 return sd_event_exit(sd_event_source_get_event(s
), r
);
2307 static int on_journal_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
2308 Context
*c
= ASSERT_PTR(userdata
);
2313 r
= sd_journal_process(c
->journal
);
2315 log_error_errno(r
, "Failed to process journal events: %m");
2316 return sd_event_exit(sd_event_source_get_event(s
), r
);
2319 return show_and_fflush(c
, s
);
2322 static int on_first_event(sd_event_source
*s
, void *userdata
) {
2323 return show_and_fflush(userdata
, s
);
2326 static int on_signal(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
2329 assert(IN_SET(si
->ssi_signo
, SIGTERM
, SIGINT
));
2331 return sd_event_exit(sd_event_source_get_event(s
), si
->ssi_signo
);
2334 static int setup_event(Context
*c
, int fd
, sd_event
**ret
) {
2335 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2343 r
= sd_event_default(&e
);
2345 return log_error_errno(r
, "Failed to allocate sd_event object: %m");
2347 (void) sd_event_add_signal(e
, NULL
, SIGTERM
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2348 (void) sd_event_add_signal(e
, NULL
, SIGINT
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2350 r
= sd_event_add_io(e
, NULL
, fd
, EPOLLIN
, &on_journal_event
, c
);
2352 return log_error_errno(r
, "Failed to add io event source for journal: %m");
2354 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2355 r
= sd_event_add_io(e
, NULL
, STDOUT_FILENO
, EPOLLHUP
|EPOLLERR
, NULL
, INT_TO_PTR(-ECANCELED
));
2357 /* Installing an epoll watch on a regular file doesn't work and fails with EPERM. Which is
2358 * totally OK, handle it gracefully. epoll_ctl() documents EPERM as the error returned when
2359 * the specified fd doesn't support epoll, hence it's safe to check for that. */
2360 log_debug_errno(r
, "Unable to install EPOLLHUP watch on stderr, not watching for hangups.");
2362 return log_error_errno(r
, "Failed to add io event source for stdout: %m");
2364 if (arg_lines
!= 0 || arg_since_set
) {
2365 r
= sd_event_add_defer(e
, NULL
, on_first_event
, c
);
2367 return log_error_errno(r
, "Failed to add defer event source: %m");
2374 static int run(int argc
, char *argv
[]) {
2375 bool need_seek
= false, since_seeked
= false, use_cursor
= false, after_cursor
= false;
2376 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2377 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2378 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2379 int n_shown
, r
, poll_fd
= -EBADF
;
2381 setlocale(LC_ALL
, "");
2384 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2385 * split up into many files. */
2386 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2388 r
= parse_argv(argc
, argv
);
2395 r
= mount_image_privately_interactively(
2398 DISSECT_IMAGE_GENERIC_ROOT
|
2399 DISSECT_IMAGE_REQUIRE_ROOT
|
2400 DISSECT_IMAGE_VALIDATE_OS
|
2401 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2402 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2404 /* ret_dir_fd= */ NULL
,
2409 arg_root
= strdup(mounted_dir
);
2414 signal(SIGWINCH
, columns_lines_cache_reset
);
2417 switch (arg_action
) {
2419 case ACTION_NEW_ID128
:
2420 return id128_print_new(ID128_PRINT_PRETTY
);
2422 case ACTION_SETUP_KEYS
:
2423 return setup_keys();
2425 case ACTION_LIST_CATALOG
:
2426 case ACTION_DUMP_CATALOG
:
2427 case ACTION_UPDATE_CATALOG
: {
2428 _cleanup_free_
char *database
= NULL
;
2430 database
= path_join(arg_root
, secure_getenv("SYSTEMD_CATALOG") ?: CATALOG_DATABASE
);
2434 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2437 e
= secure_getenv("SYSTEMD_CATALOG_SOURCES");
2442 e
? (const char* const*) STRV_MAKE(e
) : catalog_file_dirs
);
2444 return log_error_errno(r
, "Failed to list catalog: %m");
2446 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2448 pager_open(arg_pager_flags
);
2451 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2453 r
= catalog_list(stdout
, database
, oneline
);
2455 return log_error_errno(r
, "Failed to list catalog: %m");
2462 return flush_to_var();
2464 case ACTION_RELINQUISH_VAR
:
2465 return relinquish_var();
2468 return sync_journal();
2474 case ACTION_PRINT_HEADER
:
2476 case ACTION_DISK_USAGE
:
2477 case ACTION_LIST_BOOTS
:
2479 case ACTION_ROTATE_AND_VACUUM
:
2480 case ACTION_LIST_FIELDS
:
2481 case ACTION_LIST_FIELD_NAMES
:
2482 /* These ones require access to the journal files, continue below. */
2486 assert_not_reached();
2490 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2492 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2493 else if (arg_file_stdin
)
2494 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2496 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2497 else if (arg_machine
)
2498 r
= journal_open_machine(&j
, arg_machine
);
2500 r
= sd_journal_open_namespace(
2503 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2504 arg_namespace_flags
| arg_journal_type
);
2506 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2508 r
= journal_access_check_and_warn(j
, arg_quiet
,
2509 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2513 switch (arg_action
) {
2515 case ACTION_NEW_ID128
:
2516 case ACTION_SETUP_KEYS
:
2517 case ACTION_LIST_CATALOG
:
2518 case ACTION_DUMP_CATALOG
:
2519 case ACTION_UPDATE_CATALOG
:
2523 assert_not_reached();
2525 case ACTION_PRINT_HEADER
:
2526 journal_print_header(j
);
2530 return verify(j
, !arg_quiet
);
2532 case ACTION_DISK_USAGE
: {
2535 r
= sd_journal_get_usage(j
, &bytes
);
2539 printf("Archived and active journals take up %s in the file system.\n",
2540 FORMAT_BYTES(bytes
));
2545 case ACTION_LIST_BOOTS
:
2546 return list_boots(j
);
2548 case ACTION_ROTATE_AND_VACUUM
:
2556 case ACTION_VACUUM
: {
2560 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2561 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2563 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2572 case ACTION_LIST_FIELD_NAMES
: {
2575 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2576 printf("%s\n", field
);
2582 case ACTION_LIST_FIELDS
:
2586 assert_not_reached();
2589 if (arg_boot_offset
!= 0 &&
2590 sd_journal_has_runtime_files(j
) > 0 &&
2591 sd_journal_has_persistent_files(j
) == 0) {
2592 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2594 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2599 /* add_boot() must be called first!
2600 * It may need to seek the journal to find parent boot IDs. */
2611 return log_error_errno(r
, "Failed to add filter for units: %m");
2613 r
= add_syslog_identifier(j
);
2615 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2617 r
= add_priorities(j
);
2621 r
= add_facilities(j
);
2625 r
= add_matches(j
, argv
+ optind
);
2629 if (DEBUG_LOGGING
) {
2630 _cleanup_free_
char *filter
= NULL
;
2632 filter
= journal_make_match_string(j
);
2636 log_debug("Journal filter: %s", filter
);
2639 if (arg_action
== ACTION_LIST_FIELDS
)
2640 return action_list_fields(j
);
2642 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2644 poll_fd
= sd_journal_get_fd(j
);
2645 if (poll_fd
== -EMFILE
) {
2646 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2648 } else if (poll_fd
== -EMEDIUMTYPE
)
2649 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2650 else if (poll_fd
< 0)
2651 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2654 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2655 _cleanup_free_
char *cursor_from_file
= NULL
;
2656 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2658 if (arg_cursor_file
) {
2659 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2660 if (r
< 0 && r
!= -ENOENT
)
2661 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2664 cursor
= cursor_from_file
;
2665 after_cursor
= true;
2668 after_cursor
= arg_after_cursor
;
2671 r
= sd_journal_seek_cursor(j
, cursor
);
2673 return log_error_errno(r
, "Failed to seek to cursor: %m");
2681 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2683 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2685 if (after_cursor
&& r
< 2) {
2686 /* We couldn't find the next entry after the cursor. */
2693 } else if (arg_until_set
&& (arg_reverse
|| arg_lines_needs_seek_end())) {
2694 /* If both --until and any of --reverse and --lines=N is specified, things get
2695 * a little tricky. We seek to the place of --until first. If only --reverse or
2696 * --reverse and --lines is specified, we search backwards and let the output
2697 * counter handle --lines for us. If only --lines is used, we just jump backwards
2698 * arg_lines and search afterwards from there. */
2700 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2702 return log_error_errno(r
, "Failed to seek to date: %m");
2705 r
= sd_journal_previous(j
);
2706 else /* arg_lines_needs_seek_end */
2707 r
= sd_journal_previous_skip(j
, arg_lines
);
2709 } else if (arg_reverse
) {
2710 r
= sd_journal_seek_tail(j
);
2712 return log_error_errno(r
, "Failed to seek to tail: %m");
2714 r
= sd_journal_previous(j
);
2716 } else if (arg_lines_needs_seek_end()) {
2717 r
= sd_journal_seek_tail(j
);
2719 return log_error_errno(r
, "Failed to seek to tail: %m");
2721 r
= sd_journal_previous_skip(j
, arg_lines
);
2723 } else if (arg_since_set
) {
2724 /* This is placed after arg_reverse and arg_lines. If --since is used without
2725 * both, we seek to the place of --since and search afterwards from there.
2726 * If used with --reverse or --lines, we seek to the tail first and check if
2727 * the entry is within the range of --since later. */
2729 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2731 return log_error_errno(r
, "Failed to seek to date: %m");
2732 since_seeked
= true;
2734 r
= sd_journal_next(j
);
2737 r
= sd_journal_seek_head(j
);
2739 return log_error_errno(r
, "Failed to seek to head: %m");
2741 r
= sd_journal_next(j
);
2744 return log_error_errno(r
, "Failed to iterate through journal: %m");
2749 pager_open(arg_pager_flags
);
2751 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2753 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2755 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2757 return log_error_errno(r
, "Failed to get cutoff: %m");
2760 printf("-- Journal begins at %s. --\n",
2761 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2763 printf("-- Journal begins at %s, ends at %s. --\n",
2764 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2765 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2771 .need_seek
= need_seek
,
2772 .since_seeked
= since_seeked
,
2776 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2779 assert(poll_fd
>= 0);
2781 r
= setup_event(&c
, poll_fd
, &e
);
2785 r
= sd_event_loop(e
);
2790 /* unref signal event sources. */
2791 e
= sd_event_unref(e
);
2793 r
= update_cursor(j
);
2797 /* re-send the original signal. */
2798 assert(SIGNAL_VALID(sig
));
2800 log_error("Failed to raise the original signal SIG%s, ignoring: %m", signal_to_string(sig
));
2810 if (n_shown
== 0 && !arg_quiet
)
2811 printf("-- No entries --\n");
2813 r
= update_cursor(j
);
2817 if (arg_compiled_pattern
&& n_shown
== 0)
2818 /* --grep was used, no error was thrown, but the pattern didn't
2819 * match anything. Let's mimic grep's behavior here and return
2820 * a non-zero exit code, so journalctl --grep can be used
2821 * in scripts and such */
2827 DEFINE_MAIN_FUNCTION(run
);