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 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
179 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
187 if (!path_startswith(devpath
, "/dev/"))
188 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
189 "Devpath does not start with /dev/");
191 if (stat(devpath
, &st
) < 0)
192 return log_error_errno(errno
, "Couldn't stat file: %m");
194 r
= sd_device_new_from_stat_rdev(&device
, &st
);
196 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
198 for (d
= device
; d
; ) {
199 _cleanup_free_
char *match
= NULL
;
200 const char *subsys
, *sysname
, *devnode
;
203 r
= sd_device_get_subsystem(d
, &subsys
);
207 r
= sd_device_get_sysname(d
, &sysname
);
211 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
215 r
= sd_journal_add_match(j
, match
, 0);
217 return log_error_errno(r
, "Failed to add match: %m");
219 if (sd_device_get_devname(d
, &devnode
) >= 0) {
220 _cleanup_free_
char *match1
= NULL
;
222 r
= stat(devnode
, &st
);
224 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
226 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
230 r
= sd_journal_add_match(j
, match1
, 0);
232 return log_error_errno(r
, "Failed to add match: %m");
236 if (sd_device_get_parent(d
, &parent
) < 0)
242 r
= add_match_this_boot(j
, arg_machine
);
244 return log_error_errno(r
, "Failed to add match for the current boot: %m");
249 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
252 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
254 return format_timestamp(buf
, l
, t
);
257 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
258 sd_id128_t id
= SD_ID128_NULL
;
261 if (streq(x
, "all")) {
262 *boot_id
= SD_ID128_NULL
;
265 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
268 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
269 r
= sd_id128_from_string(t
, &id
);
271 x
+= SD_ID128_STRING_MAX
- 1;
273 if (!IN_SET(*x
, 0, '-', '+'))
277 r
= safe_atoi(x
, &off
);
282 r
= safe_atoi(x
, &off
);
296 static int parse_lines(const char *arg
, bool graceful
) {
300 assert(arg
|| graceful
);
305 if (streq(arg
, "all")) {
306 arg_lines
= ARG_LINES_ALL
;
310 l
= startswith(arg
, "+");
312 r
= safe_atoi(l
?: arg
, &n
);
313 if (r
< 0 || n
< 0) {
317 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse --lines='%s'.", arg
);
321 arg_lines_oldest
= l
;
327 arg_lines_oldest
= false;
331 static bool arg_lines_needs_seek_end(void) {
332 return arg_lines
>= 0 && !arg_lines_oldest
;
335 static int help_facilities(void) {
337 puts("Available facilities:");
339 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
340 _cleanup_free_
char *t
= NULL
;
342 if (log_facility_unshifted_to_string_alloc(i
, &t
))
350 static int help(void) {
351 _cleanup_free_
char *link
= NULL
;
354 pager_open(arg_pager_flags
);
356 r
= terminal_urlify_man("journalctl", "1", &link
);
360 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
361 "%5$sQuery the journal.%6$s\n\n"
362 "%3$sSource Options:%4$s\n"
363 " --system Show the system journal\n"
364 " --user Show the user journal for the current user\n"
365 " -M --machine=CONTAINER Operate on local container\n"
366 " -m --merge Show entries from all available journals\n"
367 " -D --directory=PATH Show journal files from directory\n"
368 " -i --file=PATH Show journal file\n"
369 " --root=PATH Operate on an alternate filesystem root\n"
370 " --image=PATH Operate on disk image as filesystem root\n"
371 " --image-policy=POLICY Specify disk image dissection policy\n"
372 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
373 "\n%3$sFiltering Options:%4$s\n"
374 " -S --since=DATE Show entries not older than the specified date\n"
375 " -U --until=DATE Show entries not newer than the specified date\n"
376 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
377 " --after-cursor=CURSOR Show entries after the specified cursor\n"
378 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
379 " -b --boot[=ID] Show current boot or the specified boot\n"
380 " -u --unit=UNIT Show logs from the specified unit\n"
381 " --user-unit=UNIT Show logs from the specified user unit\n"
382 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
383 " -p --priority=RANGE Show entries with the specified priority\n"
384 " --facility=FACILITY... Show entries with the specified facilities\n"
385 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
386 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
387 " -k --dmesg Show kernel message log from the current boot\n"
388 "\n%3$sOutput Control Options:%4$s\n"
389 " -o --output=STRING Change journal output mode (short, short-precise,\n"
390 " short-iso, short-iso-precise, short-full,\n"
391 " short-monotonic, short-unix, verbose, export,\n"
392 " json, json-pretty, json-sse, json-seq, cat,\n"
394 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
395 " -n --lines[=[+]INTEGER] Number of journal entries to show\n"
396 " -r --reverse Show the newest entries first\n"
397 " --show-cursor Print the cursor after all the entries\n"
398 " --utc Express time in Coordinated Universal Time (UTC)\n"
399 " -x --catalog Add message explanations where available\n"
400 " --no-hostname Suppress output of hostname field\n"
401 " --no-full Ellipsize fields\n"
402 " -a --all Show all fields, including long and unprintable\n"
403 " -f --follow Follow the journal\n"
404 " --no-tail Show all lines, even in follow mode\n"
405 " --truncate-newline Truncate entries by first newline character\n"
406 " -q --quiet Do not show info messages and privilege warning\n"
407 "\n%3$sPager Control Options:%4$s\n"
408 " --no-pager Do not pipe output into a pager\n"
409 " -e --pager-end Immediately jump to the end in the pager\n"
410 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
411 " --interval=TIME Time interval for changing the FSS sealing key\n"
412 " --verify-key=KEY Specify FSS verification key\n"
413 " --force Override of the FSS key pair with --setup-keys\n"
414 "\n%3$sCommands:%4$s\n"
415 " -h --help Show this help text\n"
416 " --version Show package version\n"
417 " -N --fields List all field names currently used\n"
418 " -F --field=FIELD List all values that a specified field takes\n"
419 " --list-boots Show terse information about recorded boots\n"
420 " --disk-usage Show total disk usage of all journal files\n"
421 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
422 " --vacuum-files=INT Leave only the specified number of journal files\n"
423 " --vacuum-time=TIME Remove journal files older than specified time\n"
424 " --verify Verify journal file consistency\n"
425 " --sync Synchronize unwritten journal messages to disk\n"
426 " --relinquish-var Stop logging to disk, log to temporary file system\n"
427 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
428 " --flush Flush all journal data from /run into /var\n"
429 " --rotate Request immediate rotation of the journal files\n"
430 " --header Show journal header information\n"
431 " --list-catalog Show all message IDs in the catalog\n"
432 " --dump-catalog Show entries in the message catalog\n"
433 " --update-catalog Update the message catalog database\n"
434 " --setup-keys Generate a new FSS key pair\n"
435 "\nSee the %2$s for details.\n",
436 program_invocation_short_name
,
446 static int parse_argv(int argc
, char *argv
[]) {
481 ARG_SMART_RELINQUISH_VAR
,
483 ARG_TRUNCATE_NEWLINE
,
492 static const struct option options
[] = {
493 { "help", no_argument
, NULL
, 'h' },
494 { "version" , no_argument
, NULL
, ARG_VERSION
},
495 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
496 { "pager-end", no_argument
, NULL
, 'e' },
497 { "follow", no_argument
, NULL
, 'f' },
498 { "force", no_argument
, NULL
, ARG_FORCE
},
499 { "output", required_argument
, NULL
, 'o' },
500 { "all", no_argument
, NULL
, 'a' },
501 { "full", no_argument
, NULL
, 'l' },
502 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
503 { "lines", optional_argument
, NULL
, 'n' },
504 { "truncate-newline", no_argument
, NULL
, ARG_TRUNCATE_NEWLINE
},
505 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
506 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
507 { "quiet", no_argument
, NULL
, 'q' },
508 { "merge", no_argument
, NULL
, 'm' },
509 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
510 { "boot", optional_argument
, NULL
, 'b' },
511 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
512 { "dmesg", no_argument
, NULL
, 'k' },
513 { "system", no_argument
, NULL
, ARG_SYSTEM
},
514 { "user", no_argument
, NULL
, ARG_USER
},
515 { "directory", required_argument
, NULL
, 'D' },
516 { "file", required_argument
, NULL
, 'i' },
517 { "root", required_argument
, NULL
, ARG_ROOT
},
518 { "image", required_argument
, NULL
, ARG_IMAGE
},
519 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
520 { "header", no_argument
, NULL
, ARG_HEADER
},
521 { "identifier", required_argument
, NULL
, 't' },
522 { "priority", required_argument
, NULL
, 'p' },
523 { "facility", required_argument
, NULL
, ARG_FACILITY
},
524 { "grep", required_argument
, NULL
, 'g' },
525 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
526 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
527 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
528 { "verify", no_argument
, NULL
, ARG_VERIFY
},
529 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
530 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
531 { "cursor", required_argument
, NULL
, 'c' },
532 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
533 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
534 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
535 { "since", required_argument
, NULL
, 'S' },
536 { "until", required_argument
, NULL
, 'U' },
537 { "unit", required_argument
, NULL
, 'u' },
538 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
539 { "field", required_argument
, NULL
, 'F' },
540 { "fields", no_argument
, NULL
, 'N' },
541 { "catalog", no_argument
, NULL
, 'x' },
542 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
543 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
544 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
545 { "reverse", no_argument
, NULL
, 'r' },
546 { "machine", required_argument
, NULL
, 'M' },
547 { "utc", no_argument
, NULL
, ARG_UTC
},
548 { "flush", no_argument
, NULL
, ARG_FLUSH
},
549 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
550 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
551 { "sync", no_argument
, NULL
, ARG_SYNC
},
552 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
553 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
554 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
555 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
556 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
557 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
558 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
567 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:i:", options
, NULL
)) >= 0)
578 arg_pager_flags
|= PAGER_DISABLE
;
582 arg_pager_flags
|= PAGER_JUMP_TO_END
;
584 if (arg_lines
== ARG_LINES_DEFAULT
)
596 if (streq(optarg
, "help")) {
597 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
601 arg_output
= output_mode_from_string(optarg
);
603 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
605 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
608 if (OUTPUT_MODE_IS_JSON(arg_output
))
609 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
611 arg_json_format_flags
= JSON_FORMAT_OFF
;
628 r
= parse_lines(optarg
?: argv
[optind
], !optarg
);
631 if (r
> 0 && !optarg
)
640 case ARG_TRUNCATE_NEWLINE
:
641 arg_truncate_newline
= true;
645 arg_action
= ACTION_NEW_ID128
;
658 arg_boot_id
= SD_ID128_NULL
;
664 arg_boot_id
= SD_ID128_NULL
;
668 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
670 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
674 /* Hmm, no argument? Maybe the next
675 * word on the command line is
676 * supposed to be the argument? Let's
677 * see if there is one and is parsable
678 * as a boot descriptor... */
679 } else if (optind
< argc
) {
680 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
689 arg_action
= ACTION_LIST_BOOTS
;
693 arg_boot
= arg_dmesg
= true;
697 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
701 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
705 arg_machine
= optarg
;
709 if (streq(optarg
, "*")) {
710 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
711 arg_namespace
= NULL
;
712 } else if (startswith(optarg
, "+")) {
713 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
714 arg_namespace
= optarg
+ 1;
715 } else if (isempty(optarg
)) {
716 arg_namespace_flags
= 0;
717 arg_namespace
= NULL
;
719 arg_namespace_flags
= 0;
720 arg_namespace
= optarg
;
726 arg_directory
= optarg
;
730 if (streq(optarg
, "-"))
731 /* An undocumented feature: we can read journal files from STDIN. We don't document
732 * this though, since after all we only support this for mmap-able, seekable files, and
733 * not for example pipes which are probably the primary use case for reading things from
734 * STDIN. To avoid confusion we hence don't document this feature. */
735 arg_file_stdin
= true;
737 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
739 return log_error_errno(r
, "Failed to add paths: %m");
744 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
750 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
755 case ARG_IMAGE_POLICY
:
756 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
765 case ARG_CURSOR_FILE
:
766 arg_cursor_file
= optarg
;
769 case ARG_AFTER_CURSOR
:
770 arg_after_cursor
= optarg
;
773 case ARG_SHOW_CURSOR
:
774 arg_show_cursor
= true;
778 arg_action
= ACTION_PRINT_HEADER
;
782 arg_action
= ACTION_VERIFY
;
786 arg_action
= ACTION_DISK_USAGE
;
789 case ARG_VACUUM_SIZE
:
790 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
792 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
794 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
797 case ARG_VACUUM_FILES
:
798 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
800 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
802 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
805 case ARG_VACUUM_TIME
:
806 r
= parse_sec(optarg
, &arg_vacuum_time
);
808 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
810 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
819 arg_action
= ACTION_SETUP_KEYS
;
823 r
= free_and_strdup(&arg_verify_key
, optarg
);
826 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
827 * in ps or htop output. */
828 memset(optarg
, 'x', strlen(optarg
));
830 arg_action
= ACTION_VERIFY
;
835 r
= parse_sec(optarg
, &arg_interval
);
836 if (r
< 0 || arg_interval
<= 0)
837 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
838 "Failed to parse sealing key change interval: %s", optarg
);
845 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
846 "Compiled without forward-secure sealing support.");
852 dots
= strstr(optarg
, "..");
854 _cleanup_free_
char *a
= NULL
;
858 a
= strndup(optarg
, dots
- optarg
);
862 from
= log_level_from_string(a
);
863 to
= log_level_from_string(dots
+ 2);
865 if (from
< 0 || to
< 0)
866 return log_error_errno(from
< 0 ? from
: to
,
867 "Failed to parse log level range %s", optarg
);
872 for (i
= from
; i
<= to
; i
++)
873 arg_priorities
|= 1 << i
;
875 for (i
= to
; i
<= from
; i
++)
876 arg_priorities
|= 1 << i
;
882 p
= log_level_from_string(optarg
);
884 return log_error_errno(p
, "Unknown log level %s", optarg
);
888 for (i
= 0; i
<= p
; i
++)
889 arg_priorities
|= 1 << i
;
899 _cleanup_free_
char *fac
= NULL
;
902 r
= extract_first_word(&p
, &fac
, ",", 0);
904 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
908 if (streq(fac
, "help")) {
913 num
= log_facility_unshifted_from_string(fac
);
915 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
917 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
925 arg_pattern
= optarg
;
928 case ARG_CASE_SENSITIVE
:
930 r
= parse_boolean(optarg
);
932 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
933 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
935 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
940 r
= parse_timestamp(optarg
, &arg_since
);
942 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
943 "Failed to parse timestamp: %s", optarg
);
944 arg_since_set
= true;
948 r
= parse_timestamp(optarg
, &arg_until
);
950 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
951 "Failed to parse timestamp: %s", optarg
);
952 arg_until_set
= true;
956 r
= strv_extend(&arg_syslog_identifier
, optarg
);
962 r
= strv_extend(&arg_system_units
, optarg
);
968 r
= strv_extend(&arg_user_units
, optarg
);
974 arg_action
= ACTION_LIST_FIELDS
;
979 arg_action
= ACTION_LIST_FIELD_NAMES
;
982 case ARG_NO_HOSTNAME
:
983 arg_no_hostname
= true;
990 case ARG_LIST_CATALOG
:
991 arg_action
= ACTION_LIST_CATALOG
;
994 case ARG_DUMP_CATALOG
:
995 arg_action
= ACTION_DUMP_CATALOG
;
998 case ARG_UPDATE_CATALOG
:
999 arg_action
= ACTION_UPDATE_CATALOG
;
1011 arg_action
= ACTION_FLUSH
;
1014 case ARG_SMART_RELINQUISH_VAR
: {
1015 int root_mnt_id
, log_mnt_id
;
1017 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
1018 * if it's on the same mount as the root file system there's no point in
1019 * relinquishing access and we can leave journald write to it until the very last
1022 r
= path_get_mnt_id("/", &root_mnt_id
);
1024 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1026 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1028 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1029 else if (root_mnt_id
== log_mnt_id
) {
1030 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1033 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1039 case ARG_RELINQUISH_VAR
:
1040 arg_action
= ACTION_RELINQUISH_VAR
;
1044 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1048 arg_action
= ACTION_SYNC
;
1051 case ARG_OUTPUT_FIELDS
: {
1052 _cleanup_strv_free_
char **v
= NULL
;
1054 v
= strv_split(optarg
, ",");
1058 r
= set_put_strdupv(&arg_output_fields
, v
);
1068 assert_not_reached();
1072 arg_lines
= ARG_LINES_ALL
;
1074 if (arg_follow
&& !arg_since_set
&& arg_lines
== ARG_LINES_DEFAULT
)
1077 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1079 arg_boot_id
= SD_ID128_NULL
;
1080 arg_boot_offset
= 0;
1083 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1084 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1085 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1087 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1088 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1089 "--since= must be before --until=.");
1091 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_cursor_file
+ !!arg_since_set
> 1)
1092 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1093 "Please specify only one of --since=, --cursor=, --cursor-file=, and --after-cursor=.");
1095 if (arg_follow
&& arg_reverse
)
1096 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1097 "Please specify either --reverse or --follow, not both.");
1099 if (arg_lines
>= 0 && arg_lines_oldest
&& (arg_reverse
|| arg_follow
))
1100 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1101 "--lines=+N is unsupported when --reverse or --follow is specified.");
1103 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1104 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1105 "Extraneous arguments starting with '%s'",
1108 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1109 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1110 "Using --boot or --list-boots with --merge is not supported.");
1112 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1113 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1114 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1115 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1116 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1120 arg_system_units
= strv_free(arg_system_units
);
1124 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1128 /* When --grep is used along with --lines without '+', i.e. when we start from the end of the
1129 * journal, we don't know how many lines we can print. So we search backwards and count until
1130 * enough lines have been printed or we hit the head.
1131 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1132 * if that is specified. */
1133 if (arg_lines_needs_seek_end() && !arg_follow
)
1140 static int add_matches(sd_journal
*j
, char **args
) {
1141 bool have_term
= false;
1145 STRV_FOREACH(i
, args
) {
1148 if (streq(*i
, "+")) {
1151 r
= sd_journal_add_disjunction(j
);
1154 } else if (path_is_absolute(*i
)) {
1155 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1158 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1160 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1162 if (lstat(p
, &st
) < 0)
1163 return log_error_errno(errno
, "Couldn't stat file: %m");
1165 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1166 if (executable_is_script(p
, &interpreter
) > 0) {
1167 _cleanup_free_
char *comm
= NULL
;
1169 r
= path_extract_filename(p
, &comm
);
1171 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1173 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1177 /* Append _EXE only if the interpreter is not a link.
1178 Otherwise, it might be outdated often. */
1179 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1180 t2
= strjoin("_EXE=", interpreter
);
1185 t
= strjoin("_EXE=", p
);
1190 r
= sd_journal_add_match(j
, t
, 0);
1193 r
= sd_journal_add_match(j
, t2
, 0);
1195 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1196 r
= add_matches_for_device(j
, p
);
1200 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1201 "File is neither a device node, nor regular file, nor executable: %s",
1206 r
= sd_journal_add_match(j
, *i
, 0);
1211 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1214 if (!strv_isempty(args
) && !have_term
)
1215 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1216 "\"+\" can only be used between terms");
1221 static int list_boots(sd_journal
*j
) {
1222 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1223 _cleanup_free_ BootId
*boots
= NULL
;
1229 r
= journal_get_boots(j
, &boots
, &n_boots
);
1231 return log_error_errno(r
, "Failed to determine boots: %m");
1235 table
= table_new("idx", "boot id", "first entry", "last entry");
1240 table_set_width(table
, 0);
1242 r
= table_set_json_field_name(table
, 0, "index");
1244 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1246 (void) table_set_sort(table
, (size_t) 0);
1247 (void) table_set_reverse(table
, 0, arg_reverse
);
1249 FOREACH_ARRAY(i
, boots
, n_boots
) {
1250 r
= table_add_many(table
,
1251 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1252 TABLE_SET_ALIGN_PERCENT
, 100,
1254 TABLE_TIMESTAMP
, i
->first_usec
,
1255 TABLE_TIMESTAMP
, i
->last_usec
);
1257 return table_log_add_error(r
);
1260 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1262 return table_log_print_error(r
);
1267 static int add_boot(sd_journal
*j
) {
1275 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1276 * We can do this only when we logs are coming from the current machine,
1277 * so take the slow path if log location is specified. */
1278 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1279 !arg_directory
&& !arg_file
&& !arg_root
)
1280 return add_match_this_boot(j
, arg_machine
);
1282 if (sd_id128_is_null(arg_boot_id
)) {
1283 r
= journal_find_boot_by_offset(j
, arg_boot_offset
, &arg_boot_id
);
1285 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1288 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1289 "No journal boot entry found from the specified boot offset (%+i).",
1292 r
= journal_find_boot_by_id(j
, arg_boot_id
);
1294 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1295 SD_ID128_TO_STRING(arg_boot_id
));
1297 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1298 "No journal boot entry found from the specified boot ID (%s).",
1299 SD_ID128_TO_STRING(arg_boot_id
));
1302 r
= add_match_boot_id(j
, arg_boot_id
);
1304 return log_error_errno(r
, "Failed to add match: %m");
1306 r
= sd_journal_add_conjunction(j
);
1308 return log_error_errno(r
, "Failed to add conjunction: %m");
1313 static int add_dmesg(sd_journal
*j
) {
1320 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1321 STRLEN("_TRANSPORT=kernel"));
1323 return log_error_errno(r
, "Failed to add match: %m");
1325 r
= sd_journal_add_conjunction(j
);
1327 return log_error_errno(r
, "Failed to add conjunction: %m");
1332 static int get_possible_units(
1338 _cleanup_set_free_free_ Set
*found
= NULL
;
1341 found
= set_new(&string_hash_ops
);
1345 NULSTR_FOREACH(field
, fields
) {
1349 r
= sd_journal_query_unique(j
, field
);
1353 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1356 _cleanup_free_
char *u
= NULL
;
1358 eq
= memchr(data
, '=', size
);
1360 prefix
= eq
- (char*) data
+ 1;
1364 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1368 STRV_FOREACH(pattern
, patterns
)
1369 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1370 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1372 r
= set_consume(found
, u
);
1374 if (r
< 0 && r
!= -EEXIST
)
1382 *units
= TAKE_PTR(found
);
1387 /* This list is supposed to return the superset of unit names
1388 * possibly matched by rules added with add_matches_for_unit... */
1389 #define SYSTEM_UNITS \
1393 "OBJECT_SYSTEMD_UNIT\0" \
1396 /* ... and add_matches_for_user_unit */
1397 #define USER_UNITS \
1398 "_SYSTEMD_USER_UNIT\0" \
1400 "COREDUMP_USER_UNIT\0" \
1401 "OBJECT_SYSTEMD_USER_UNIT\0" \
1402 "_SYSTEMD_USER_SLICE\0"
1404 static int add_units(sd_journal
*j
) {
1405 _cleanup_strv_free_
char **patterns
= NULL
;
1410 STRV_FOREACH(i
, arg_system_units
) {
1411 _cleanup_free_
char *u
= NULL
;
1413 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1417 if (string_is_glob(u
)) {
1418 r
= strv_push(&patterns
, u
);
1423 r
= add_matches_for_unit(j
, u
);
1426 r
= sd_journal_add_disjunction(j
);
1433 if (!strv_isempty(patterns
)) {
1434 _cleanup_set_free_free_ Set
*units
= NULL
;
1437 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1441 SET_FOREACH(u
, units
) {
1442 r
= add_matches_for_unit(j
, u
);
1445 r
= sd_journal_add_disjunction(j
);
1452 patterns
= strv_free(patterns
);
1454 STRV_FOREACH(i
, arg_user_units
) {
1455 _cleanup_free_
char *u
= NULL
;
1457 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1461 if (string_is_glob(u
)) {
1462 r
= strv_push(&patterns
, u
);
1467 r
= add_matches_for_user_unit(j
, u
, getuid());
1470 r
= sd_journal_add_disjunction(j
);
1477 if (!strv_isempty(patterns
)) {
1478 _cleanup_set_free_free_ Set
*units
= NULL
;
1481 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1485 SET_FOREACH(u
, units
) {
1486 r
= add_matches_for_user_unit(j
, u
, getuid());
1489 r
= sd_journal_add_disjunction(j
);
1496 /* Complain if the user request matches but nothing whatsoever was
1497 * found, since otherwise everything would be matched. */
1498 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1501 r
= sd_journal_add_conjunction(j
);
1508 static int add_priorities(sd_journal
*j
) {
1509 char match
[] = "PRIORITY=0";
1513 if (arg_priorities
== 0xFF)
1516 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1517 if (arg_priorities
& (1 << i
)) {
1518 match
[sizeof(match
)-2] = '0' + i
;
1520 r
= sd_journal_add_match(j
, match
, strlen(match
));
1522 return log_error_errno(r
, "Failed to add match: %m");
1525 r
= sd_journal_add_conjunction(j
);
1527 return log_error_errno(r
, "Failed to add conjunction: %m");
1532 static int add_facilities(sd_journal
*j
) {
1536 SET_FOREACH(p
, arg_facilities
) {
1537 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1539 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1541 r
= sd_journal_add_match(j
, match
, strlen(match
));
1543 return log_error_errno(r
, "Failed to add match: %m");
1549 static int add_syslog_identifier(sd_journal
*j
) {
1554 STRV_FOREACH(i
, arg_syslog_identifier
) {
1555 _cleanup_free_
char *u
= NULL
;
1557 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1560 r
= sd_journal_add_match(j
, u
, 0);
1563 r
= sd_journal_add_disjunction(j
);
1568 r
= sd_journal_add_conjunction(j
);
1576 static int format_journal_url(
1586 _cleanup_(memstream_done
) MemStream m
= {};
1590 assert(seed_size
> 0);
1592 f
= memstream_init(&m
);
1599 for (size_t i
= 0; i
< seed_size
; i
++) {
1600 if (i
> 0 && i
% 3 == 0)
1602 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1605 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1608 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1610 fprintf(f
, ";hostname=%s", hn
);
1613 return memstream_finalize(&m
, ret_url
, NULL
);
1617 static int setup_keys(void) {
1619 size_t mpk_size
, seed_size
, state_size
;
1620 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1621 _cleanup_free_
char *p
= NULL
;
1622 uint8_t *mpk
, *seed
, *state
;
1623 _cleanup_close_
int fd
= -EBADF
;
1624 sd_id128_t machine
, boot
;
1629 r
= stat("/var/log/journal", &st
);
1630 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1631 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1633 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1634 log_error("%s is not a directory, must be using persistent logging for FSS.",
1635 "/var/log/journal");
1636 return r
< 0 ? -errno
: -ENOTDIR
;
1639 r
= sd_id128_get_machine(&machine
);
1641 return log_error_errno(r
, "Failed to get machine ID: %m");
1643 r
= sd_id128_get_boot(&boot
);
1645 return log_error_errno(r
, "Failed to get boot ID: %m");
1647 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1648 SD_ID128_FORMAT_VAL(machine
)) < 0)
1653 if (r
< 0 && errno
!= ENOENT
)
1654 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1655 } else if (access(p
, F_OK
) >= 0)
1656 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1657 "Sealing key file %s exists already. Use --force to recreate.", p
);
1659 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1660 SD_ID128_FORMAT_VAL(machine
)) < 0)
1663 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1664 mpk
= alloca_safe(mpk_size
);
1666 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1667 seed
= alloca_safe(seed_size
);
1669 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1670 state
= alloca_safe(state_size
);
1672 log_info("Generating seed...");
1673 r
= crypto_random_bytes(seed
, seed_size
);
1675 return log_error_errno(r
, "Failed to acquire random seed: %m");
1677 log_info("Generating key pair...");
1678 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1680 log_info("Generating sealing key...");
1681 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1683 assert(arg_interval
> 0);
1685 n
= now(CLOCK_REALTIME
);
1689 fd
= mkostemp_safe(k
);
1691 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1693 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1695 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1696 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1698 struct FSSHeader h
= {
1699 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1700 .machine_id
= machine
,
1702 .header_size
= htole64(sizeof(h
)),
1703 .start_usec
= htole64(n
* arg_interval
),
1704 .interval_usec
= htole64(arg_interval
),
1705 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1706 .fsprg_state_size
= htole64(state_size
),
1709 r
= loop_write(fd
, &h
, sizeof(h
));
1711 return log_error_errno(r
, "Failed to write header: %m");
1713 r
= loop_write(fd
, state
, state_size
);
1715 return log_error_errno(r
, "Failed to write state: %m");
1717 if (rename(k
, p
) < 0)
1718 return log_error_errno(errno
, "Failed to link file: %m");
1722 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1724 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1729 hn
= gethostname_malloc();
1731 hostname_cleanup(hn
);
1734 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1736 "The %ssecret sealing key%s has been written to the following local file.\n"
1737 "This key file is automatically updated when the sealing key is advanced.\n"
1738 "It should not be used on multiple hosts.\n"
1742 "The sealing key is automatically changed every %s.\n"
1744 "Please write down the following %ssecret verification key%s. It should be stored\n"
1745 "in a safe location and should not be saved locally on disk.\n"
1747 strempty(hn
), hn
? "/" : "",
1748 SD_ID128_FORMAT_VAL(machine
),
1749 ansi_highlight(), ansi_normal(),
1751 FORMAT_TIMESPAN(arg_interval
, 0),
1752 ansi_highlight(), ansi_normal(),
1753 ansi_highlight_red());
1760 fprintf(stderr
, "%s", ansi_normal());
1762 _cleanup_free_
char *url
= NULL
;
1763 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1767 (void) print_qrcode(stderr
,
1768 "To transfer the verification key to your phone scan the QR code below",
1775 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1776 "Forward-secure sealing not available.");
1780 static int verify(sd_journal
*j
, bool verbose
) {
1786 log_show_color(true);
1788 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1790 usec_t first
= 0, validated
= 0, last
= 0;
1793 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1794 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1797 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1799 /* If the key was invalid give up right-away. */
1802 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1804 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1805 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1807 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1808 if (validated
> 0) {
1809 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1810 "=> Validated from %s to %s, final %s entries not sealed.",
1811 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1812 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1813 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
1814 } else if (last
> 0)
1815 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1816 "=> No sealing yet, %s of entries not sealed.",
1817 FORMAT_TIMESPAN(last
- first
, 0));
1819 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1820 "=> No sealing yet, no entries in file.");
1828 static int simple_varlink_call(const char *option
, const char *method
) {
1829 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
1830 const char *error
, *fn
;
1834 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
1836 fn
= arg_namespace
?
1837 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
1838 "/run/systemd/journal/io.systemd.journal";
1840 r
= varlink_connect_address(&link
, fn
);
1842 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
1844 (void) varlink_set_description(link
, "journal");
1845 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
1847 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
1849 return log_error_errno(r
, "Failed to execute varlink call: %m");
1851 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
1852 "Failed to execute varlink call: %s", error
);
1857 static int flush_to_var(void) {
1858 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1859 return 0; /* Already flushed, no need to contact journald */
1860 if (errno
!= ENOENT
)
1861 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
1863 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
1866 static int relinquish_var(void) {
1867 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
1870 static int rotate(void) {
1871 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
1874 static int sync_journal(void) {
1875 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
1878 static int action_list_fields(sd_journal
*j
) {
1885 r
= sd_journal_set_data_threshold(j
, 0);
1887 return log_error_errno(r
, "Failed to unset data size threshold: %m");
1889 r
= sd_journal_query_unique(j
, arg_field
);
1891 return log_error_errno(r
, "Failed to query unique data objects: %m");
1893 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1896 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
1899 eq
= memchr(data
, '=', size
);
1901 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
1903 printf("%.*s\n", (int) size
, (const char*) data
);
1911 static int update_cursor(sd_journal
*j
) {
1912 _cleanup_free_
char *cursor
= NULL
;
1917 if (!arg_show_cursor
&& !arg_cursor_file
)
1920 r
= sd_journal_get_cursor(j
, &cursor
);
1921 if (r
== -EADDRNOTAVAIL
)
1924 return log_error_errno(r
, "Failed to get cursor: %m");
1926 if (arg_show_cursor
)
1927 printf("-- cursor: %s\n", cursor
);
1929 if (arg_cursor_file
) {
1930 r
= write_string_file(arg_cursor_file
, cursor
, WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_ATOMIC
);
1932 return log_error_errno(r
, "Failed to write new cursor to %s: %m", arg_cursor_file
);
1938 typedef struct Context
{
1939 sd_journal
*journal
;
1943 bool previous_boot_id_valid
;
1944 sd_id128_t previous_boot_id
;
1945 sd_id128_t previous_boot_id_output
;
1946 dual_timestamp previous_ts_output
;
1949 static int show(Context
*c
) {
1955 j
= ASSERT_PTR(c
->journal
);
1957 while (arg_lines
< 0 || n_shown
< arg_lines
|| arg_follow
) {
1959 size_t highlight
[2] = {};
1962 r
= sd_journal_step_one(j
, !arg_reverse
);
1964 return log_error_errno(r
, "Failed to iterate through journal: %m");
1969 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
1970 /* If --lines= is set, we usually rely on the n_shown to tell us
1971 * when to stop. However, if --since= is set too, we may end up
1972 * having less than --lines= to output. In this case let's also
1973 * check if the entry is in range. */
1977 r
= sd_journal_get_realtime_usec(j
, &usec
);
1979 return log_error_errno(r
, "Failed to determine timestamp: %m");
1980 if (usec
> arg_until
)
1984 if (arg_since_set
&& (arg_reverse
|| !c
->since_seeked
)) {
1987 r
= sd_journal_get_realtime_usec(j
, &usec
);
1989 return log_error_errno(r
, "Failed to determine timestamp: %m");
1991 if (usec
< arg_since
) {
1993 break; /* Reached the earliest entry */
1995 /* arg_lines >= 0 (!since_seeked):
1996 * We jumped arg_lines back and it seems to be too much */
1997 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
1999 return log_error_errno(r
, "Failed to seek to date: %m");
2000 c
->since_seeked
= true;
2002 c
->need_seek
= true;
2005 c
->since_seeked
= true; /* We're surely within the range of --since now */
2008 if (!arg_merge
&& !arg_quiet
) {
2011 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2013 if (c
->previous_boot_id_valid
&&
2014 !sd_id128_equal(boot_id
, c
->previous_boot_id
))
2015 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2016 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2018 c
->previous_boot_id
= boot_id
;
2019 c
->previous_boot_id_valid
= true;
2023 if (arg_compiled_pattern
) {
2024 const void *message
;
2027 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2030 c
->need_seek
= true;
2034 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2037 assert_se(message
= startswith(message
, "MESSAGE="));
2039 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2040 len
- strlen("MESSAGE="), highlight
);
2044 c
->need_seek
= true;
2050 arg_all
* OUTPUT_SHOW_ALL
|
2051 arg_full
* OUTPUT_FULL_WIDTH
|
2052 colors_enabled() * OUTPUT_COLOR
|
2053 arg_catalog
* OUTPUT_CATALOG
|
2054 arg_utc
* OUTPUT_UTC
|
2055 arg_truncate_newline
* OUTPUT_TRUNCATE_NEWLINE
|
2056 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2058 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2059 arg_output_fields
, highlight
, &c
->ellipsized
,
2060 &c
->previous_ts_output
, &c
->previous_boot_id_output
);
2061 c
->need_seek
= true;
2062 if (r
== -EADDRNOTAVAIL
)
2069 /* If journalctl take a long time to process messages, and during that time journal file
2070 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2071 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2072 * in the "following" case. By periodically calling sd_journal_process() during the processing
2073 * loop we shrink the window of time a client instance has open file descriptors for rotated
2074 * (deleted) journal files. */
2075 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2076 r
= sd_journal_process(j
);
2078 return log_error_errno(r
, "Failed to process inotify events: %m");
2085 static int show_and_fflush(Context
*c
, sd_event_source
*s
) {
2093 return sd_event_exit(sd_event_source_get_event(s
), r
);
2099 static int on_journal_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
2100 Context
*c
= ASSERT_PTR(userdata
);
2105 r
= sd_journal_process(c
->journal
);
2107 log_error_errno(r
, "Failed to process journal events: %m");
2108 return sd_event_exit(sd_event_source_get_event(s
), r
);
2111 return show_and_fflush(c
, s
);
2114 static int on_first_event(sd_event_source
*s
, void *userdata
) {
2115 return show_and_fflush(userdata
, s
);
2118 static int on_signal(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
2121 assert(IN_SET(si
->ssi_signo
, SIGTERM
, SIGINT
));
2123 return sd_event_exit(sd_event_source_get_event(s
), si
->ssi_signo
);
2126 static int setup_event(Context
*c
, int fd
, sd_event
**ret
) {
2127 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2135 r
= sd_event_default(&e
);
2137 return log_error_errno(r
, "Failed to allocate sd_event object: %m");
2139 (void) sd_event_add_signal(e
, NULL
, SIGTERM
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2140 (void) sd_event_add_signal(e
, NULL
, SIGINT
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2142 r
= sd_event_add_io(e
, NULL
, fd
, EPOLLIN
, &on_journal_event
, c
);
2144 return log_error_errno(r
, "Failed to add io event source for journal: %m");
2146 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2147 r
= sd_event_add_io(e
, NULL
, STDOUT_FILENO
, EPOLLHUP
|EPOLLERR
, NULL
, INT_TO_PTR(-ECANCELED
));
2149 /* Installing an epoll watch on a regular file doesn't work and fails with EPERM. Which is
2150 * totally OK, handle it gracefully. epoll_ctl() documents EPERM as the error returned when
2151 * the specified fd doesn't support epoll, hence it's safe to check for that. */
2152 log_debug_errno(r
, "Unable to install EPOLLHUP watch on stderr, not watching for hangups.");
2154 return log_error_errno(r
, "Failed to add io event source for stdout: %m");
2156 if (arg_lines
!= 0 || arg_since_set
) {
2157 r
= sd_event_add_defer(e
, NULL
, on_first_event
, c
);
2159 return log_error_errno(r
, "Failed to add defer event source: %m");
2166 static int run(int argc
, char *argv
[]) {
2167 bool need_seek
= false, since_seeked
= false, after_cursor
= false;
2168 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2169 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2170 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2171 _cleanup_free_
char *cursor_from_file
= NULL
;
2172 const char *cursor
= NULL
;
2173 int n_shown
, r
, poll_fd
= -EBADF
;
2175 setlocale(LC_ALL
, "");
2178 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2179 * split up into many files. */
2180 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2182 r
= parse_argv(argc
, argv
);
2189 r
= mount_image_privately_interactively(
2192 DISSECT_IMAGE_GENERIC_ROOT
|
2193 DISSECT_IMAGE_REQUIRE_ROOT
|
2194 DISSECT_IMAGE_VALIDATE_OS
|
2195 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2196 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2198 /* ret_dir_fd= */ NULL
,
2203 arg_root
= strdup(mounted_dir
);
2208 signal(SIGWINCH
, columns_lines_cache_reset
);
2211 switch (arg_action
) {
2213 case ACTION_NEW_ID128
:
2214 return id128_print_new(ID128_PRINT_PRETTY
);
2216 case ACTION_SETUP_KEYS
:
2217 return setup_keys();
2219 case ACTION_LIST_CATALOG
:
2220 case ACTION_DUMP_CATALOG
:
2221 case ACTION_UPDATE_CATALOG
: {
2222 _cleanup_free_
char *database
= NULL
;
2224 database
= path_join(arg_root
, secure_getenv("SYSTEMD_CATALOG") ?: CATALOG_DATABASE
);
2228 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2231 e
= secure_getenv("SYSTEMD_CATALOG_SOURCES");
2236 e
? (const char* const*) STRV_MAKE(e
) : catalog_file_dirs
);
2238 return log_error_errno(r
, "Failed to list catalog: %m");
2240 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2242 pager_open(arg_pager_flags
);
2245 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2247 r
= catalog_list(stdout
, database
, oneline
);
2249 return log_error_errno(r
, "Failed to list catalog: %m");
2256 return flush_to_var();
2258 case ACTION_RELINQUISH_VAR
:
2259 return relinquish_var();
2262 return sync_journal();
2268 case ACTION_PRINT_HEADER
:
2270 case ACTION_DISK_USAGE
:
2271 case ACTION_LIST_BOOTS
:
2273 case ACTION_ROTATE_AND_VACUUM
:
2274 case ACTION_LIST_FIELDS
:
2275 case ACTION_LIST_FIELD_NAMES
:
2276 /* These ones require access to the journal files, continue below. */
2280 assert_not_reached();
2284 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2286 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2287 else if (arg_file_stdin
)
2288 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2290 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2291 else if (arg_machine
)
2292 r
= journal_open_machine(&j
, arg_machine
);
2294 r
= sd_journal_open_namespace(
2297 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2298 arg_namespace_flags
| arg_journal_type
);
2300 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2302 r
= journal_access_check_and_warn(j
, arg_quiet
,
2303 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2307 switch (arg_action
) {
2309 case ACTION_NEW_ID128
:
2310 case ACTION_SETUP_KEYS
:
2311 case ACTION_LIST_CATALOG
:
2312 case ACTION_DUMP_CATALOG
:
2313 case ACTION_UPDATE_CATALOG
:
2317 assert_not_reached();
2319 case ACTION_PRINT_HEADER
:
2320 journal_print_header(j
);
2324 return verify(j
, !arg_quiet
);
2326 case ACTION_DISK_USAGE
: {
2329 r
= sd_journal_get_usage(j
, &bytes
);
2333 printf("Archived and active journals take up %s in the file system.\n",
2334 FORMAT_BYTES(bytes
));
2339 case ACTION_LIST_BOOTS
:
2340 return list_boots(j
);
2342 case ACTION_ROTATE_AND_VACUUM
:
2350 case ACTION_VACUUM
: {
2354 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2355 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2357 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2366 case ACTION_LIST_FIELD_NAMES
: {
2369 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2370 printf("%s\n", field
);
2376 case ACTION_LIST_FIELDS
:
2380 assert_not_reached();
2383 if (arg_boot_offset
!= 0 &&
2384 sd_journal_has_runtime_files(j
) > 0 &&
2385 sd_journal_has_persistent_files(j
) == 0) {
2386 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2388 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2393 /* add_boot() must be called first!
2394 * It may need to seek the journal to find parent boot IDs. */
2405 return log_error_errno(r
, "Failed to add filter for units: %m");
2407 r
= add_syslog_identifier(j
);
2409 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2411 r
= add_priorities(j
);
2415 r
= add_facilities(j
);
2419 r
= add_matches(j
, argv
+ optind
);
2423 if (DEBUG_LOGGING
) {
2424 _cleanup_free_
char *filter
= NULL
;
2426 filter
= journal_make_match_string(j
);
2430 log_debug("Journal filter: %s", filter
);
2433 if (arg_action
== ACTION_LIST_FIELDS
)
2434 return action_list_fields(j
);
2436 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2438 poll_fd
= sd_journal_get_fd(j
);
2439 if (poll_fd
== -EMFILE
) {
2440 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2442 } else if (poll_fd
== -EMEDIUMTYPE
)
2443 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2444 else if (poll_fd
< 0)
2445 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2448 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2449 cursor
= arg_cursor
?: arg_after_cursor
;
2451 if (arg_cursor_file
) {
2452 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2453 if (r
< 0 && r
!= -ENOENT
)
2454 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2457 cursor
= cursor_from_file
;
2458 after_cursor
= true;
2461 after_cursor
= arg_after_cursor
;
2465 r
= sd_journal_seek_cursor(j
, cursor
);
2467 return log_error_errno(r
, "Failed to seek to cursor: %m");
2469 r
= sd_journal_step_one(j
, !arg_reverse
);
2471 return log_error_errno(r
, "Failed to iterate through journal: %m");
2473 if (after_cursor
&& r
> 0) {
2474 /* With --after-cursor=/--cursor-file= we want to skip the first entry only if it's
2475 * the entry the cursor is pointing at, otherwise, if some journal filters are used,
2476 * we might skip the first entry of the filter match, which leads to unexpectedly
2477 * missing journal entries. */
2480 k
= sd_journal_test_cursor(j
, cursor
);
2482 return log_error_errno(k
, "Failed to test cursor against current entry: %m");
2484 /* Current entry matches the one our cursor is pointing at, so let's try
2485 * to advance the next entry. */
2486 r
= sd_journal_step_one(j
, !arg_reverse
);
2490 /* We couldn't find the next entry after the cursor. */
2496 } else if (arg_until_set
&& (arg_reverse
|| arg_lines_needs_seek_end())) {
2497 /* If both --until and any of --reverse and --lines=N is specified, things get
2498 * a little tricky. We seek to the place of --until first. If only --reverse or
2499 * --reverse and --lines is specified, we search backwards and let the output
2500 * counter handle --lines for us. If only --lines is used, we just jump backwards
2501 * arg_lines and search afterwards from there. */
2503 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2505 return log_error_errno(r
, "Failed to seek to date: %m");
2508 r
= sd_journal_previous(j
);
2509 else /* arg_lines_needs_seek_end */
2510 r
= sd_journal_previous_skip(j
, arg_lines
);
2512 } else if (arg_reverse
) {
2513 r
= sd_journal_seek_tail(j
);
2515 return log_error_errno(r
, "Failed to seek to tail: %m");
2517 r
= sd_journal_previous(j
);
2519 } else if (arg_lines_needs_seek_end()) {
2520 r
= sd_journal_seek_tail(j
);
2522 return log_error_errno(r
, "Failed to seek to tail: %m");
2524 r
= sd_journal_previous_skip(j
, arg_lines
);
2526 } else if (arg_since_set
) {
2527 /* This is placed after arg_reverse and arg_lines. If --since is used without
2528 * both, we seek to the place of --since and search afterwards from there.
2529 * If used with --reverse or --lines, we seek to the tail first and check if
2530 * the entry is within the range of --since later. */
2532 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2534 return log_error_errno(r
, "Failed to seek to date: %m");
2535 since_seeked
= true;
2537 r
= sd_journal_next(j
);
2540 r
= sd_journal_seek_head(j
);
2542 return log_error_errno(r
, "Failed to seek to head: %m");
2544 r
= sd_journal_next(j
);
2547 return log_error_errno(r
, "Failed to iterate through journal: %m");
2552 pager_open(arg_pager_flags
);
2554 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2556 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2558 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2560 return log_error_errno(r
, "Failed to get cutoff: %m");
2563 printf("-- Journal begins at %s. --\n",
2564 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2566 printf("-- Journal begins at %s, ends at %s. --\n",
2567 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2568 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2574 .need_seek
= need_seek
,
2575 .since_seeked
= since_seeked
,
2579 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2582 assert(poll_fd
>= 0);
2584 r
= setup_event(&c
, poll_fd
, &e
);
2588 r
= sd_event_loop(e
);
2593 /* unref signal event sources. */
2594 e
= sd_event_unref(e
);
2596 r
= update_cursor(j
);
2600 /* re-send the original signal. */
2601 assert(SIGNAL_VALID(sig
));
2603 log_error("Failed to raise the original signal SIG%s, ignoring: %m", signal_to_string(sig
));
2613 if (n_shown
== 0 && !arg_quiet
)
2614 printf("-- No entries --\n");
2616 r
= update_cursor(j
);
2620 if (arg_compiled_pattern
&& n_shown
== 0)
2621 /* --grep was used, no error was thrown, but the pattern didn't
2622 * match anything. Let's mimic grep's behavior here and return
2623 * a non-zero exit code, so journalctl --grep can be used
2624 * in scripts and such */
2630 DEFINE_MAIN_FUNCTION(run
);