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"
27 #include "chattr-util.h"
28 #include "constants.h"
29 #include "devnum-util.h"
30 #include "dissect-image.h"
33 #include "format-table.h"
34 #include "format-util.h"
37 #include "glob-util.h"
38 #include "hostname-util.h"
39 #include "id128-print.h"
41 #include "journal-def.h"
42 #include "journal-internal.h"
43 #include "journal-util.h"
44 #include "journal-vacuum.h"
45 #include "journal-verify.h"
46 #include "locale-util.h"
48 #include "logs-show.h"
49 #include "main-func.h"
50 #include "memory-util.h"
51 #include "missing_sched.h"
53 #include "mount-util.h"
54 #include "mountpoint-util.h"
55 #include "nulstr-util.h"
57 #include "parse-argument.h"
58 #include "parse-util.h"
59 #include "path-util.h"
60 #include "pcre2-util.h"
61 #include "pretty-print.h"
62 #include "qrcode-util.h"
63 #include "random-util.h"
64 #include "rlimit-util.h"
67 #include "static-destruct.h"
68 #include "stdio-util.h"
69 #include "string-table.h"
71 #include "syslog-util.h"
72 #include "terminal-util.h"
73 #include "tmpfile-util.h"
74 #include "unit-name.h"
75 #include "user-util.h"
78 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
79 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
82 /* Special values for arg_lines */
83 ARG_LINES_DEFAULT
= -2,
87 static OutputMode arg_output
= OUTPUT_SHORT
;
88 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
89 static bool arg_utc
= false;
90 static bool arg_follow
= false;
91 static bool arg_full
= true;
92 static bool arg_all
= false;
93 static PagerFlags arg_pager_flags
= 0;
94 static int arg_lines
= ARG_LINES_DEFAULT
;
95 static bool arg_no_tail
= false;
96 static bool arg_quiet
= false;
97 static bool arg_merge
= false;
98 static bool arg_boot
= false;
99 static sd_id128_t arg_boot_id
= {};
100 static int arg_boot_offset
= 0;
101 static bool arg_dmesg
= false;
102 static bool arg_no_hostname
= false;
103 static const char *arg_cursor
= NULL
;
104 static const char *arg_cursor_file
= NULL
;
105 static const char *arg_after_cursor
= NULL
;
106 static bool arg_show_cursor
= false;
107 static const char *arg_directory
= NULL
;
108 static char **arg_file
= NULL
;
109 static bool arg_file_stdin
= false;
110 static int arg_priorities
= 0xFF;
111 static Set
*arg_facilities
= NULL
;
112 static char *arg_verify_key
= NULL
;
114 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
115 static bool arg_force
= false;
117 static usec_t arg_since
, arg_until
;
118 static bool arg_since_set
= false, arg_until_set
= false;
119 static char **arg_syslog_identifier
= NULL
;
120 static char **arg_system_units
= NULL
;
121 static char **arg_user_units
= NULL
;
122 static const char *arg_field
= NULL
;
123 static bool arg_catalog
= false;
124 static bool arg_reverse
= false;
125 static int arg_journal_type
= 0;
126 static int arg_namespace_flags
= 0;
127 static char *arg_root
= NULL
;
128 static char *arg_image
= NULL
;
129 static const char *arg_machine
= NULL
;
130 static const char *arg_namespace
= NULL
;
131 static uint64_t arg_vacuum_size
= 0;
132 static uint64_t arg_vacuum_n_files
= 0;
133 static usec_t arg_vacuum_time
= 0;
134 static Set
*arg_output_fields
= NULL
;
135 static const char *arg_pattern
= NULL
;
136 static pcre2_code
*arg_compiled_pattern
= NULL
;
137 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
138 ImagePolicy
*arg_image_policy
= NULL
;
140 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
141 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
142 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
143 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
144 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
148 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
161 ACTION_UPDATE_CATALOG
,
164 ACTION_RELINQUISH_VAR
,
168 ACTION_ROTATE_AND_VACUUM
,
170 ACTION_LIST_FIELD_NAMES
,
171 } arg_action
= ACTION_SHOW
;
173 typedef struct BootId
{
177 LIST_FIELDS(struct BootId
, boot_list
);
180 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
181 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
189 if (!path_startswith(devpath
, "/dev/"))
190 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
191 "Devpath does not start with /dev/");
193 if (stat(devpath
, &st
) < 0)
194 return log_error_errno(errno
, "Couldn't stat file: %m");
196 r
= sd_device_new_from_stat_rdev(&device
, &st
);
198 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
200 for (d
= device
; d
; ) {
201 _cleanup_free_
char *match
= NULL
;
202 const char *subsys
, *sysname
, *devnode
;
205 r
= sd_device_get_subsystem(d
, &subsys
);
209 r
= sd_device_get_sysname(d
, &sysname
);
213 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
217 r
= sd_journal_add_match(j
, match
, 0);
219 return log_error_errno(r
, "Failed to add match: %m");
221 if (sd_device_get_devname(d
, &devnode
) >= 0) {
222 _cleanup_free_
char *match1
= NULL
;
224 r
= stat(devnode
, &st
);
226 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
228 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
232 r
= sd_journal_add_match(j
, match1
, 0);
234 return log_error_errno(r
, "Failed to add match: %m");
238 if (sd_device_get_parent(d
, &parent
) < 0)
244 r
= add_match_this_boot(j
, arg_machine
);
246 return log_error_errno(r
, "Failed to add match for the current boot: %m");
251 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
254 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
256 return format_timestamp(buf
, l
, t
);
259 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
260 sd_id128_t id
= SD_ID128_NULL
;
263 if (streq(x
, "all")) {
264 *boot_id
= SD_ID128_NULL
;
267 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
270 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
271 r
= sd_id128_from_string(t
, &id
);
273 x
+= SD_ID128_STRING_MAX
- 1;
275 if (!IN_SET(*x
, 0, '-', '+'))
279 r
= safe_atoi(x
, &off
);
284 r
= safe_atoi(x
, &off
);
298 static int help_facilities(void) {
300 puts("Available facilities:");
302 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
303 _cleanup_free_
char *t
= NULL
;
305 if (log_facility_unshifted_to_string_alloc(i
, &t
))
313 static int help(void) {
314 _cleanup_free_
char *link
= NULL
;
317 pager_open(arg_pager_flags
);
319 r
= terminal_urlify_man("journalctl", "1", &link
);
323 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
324 "%5$sQuery the journal.%6$s\n\n"
325 "%3$sSource Options:%4$s\n"
326 " --system Show the system journal\n"
327 " --user Show the user journal for the current user\n"
328 " -M --machine=CONTAINER Operate on local container\n"
329 " -m --merge Show entries from all available journals\n"
330 " -D --directory=PATH Show journal files from directory\n"
331 " --file=PATH Show journal file\n"
332 " --root=PATH Operate on an alternate filesystem root\n"
333 " --image=PATH Operate on disk image as filesystem root\n"
334 " --image-policy=POLICY Specify disk image dissection policy\n"
335 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
336 "\n%3$sFiltering Options:%4$s\n"
337 " -S --since=DATE Show entries not older than the specified date\n"
338 " -U --until=DATE Show entries not newer than the specified date\n"
339 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
340 " --after-cursor=CURSOR Show entries after the specified cursor\n"
341 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
342 " -b --boot[=ID] Show current boot or the specified boot\n"
343 " -u --unit=UNIT Show logs from the specified unit\n"
344 " --user-unit=UNIT Show logs from the specified user unit\n"
345 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
346 " -p --priority=RANGE Show entries with the specified priority\n"
347 " --facility=FACILITY... Show entries with the specified facilities\n"
348 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
349 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
350 " -k --dmesg Show kernel message log from the current boot\n"
351 "\n%3$sOutput Control Options:%4$s\n"
352 " -o --output=STRING Change journal output mode (short, short-precise,\n"
353 " short-iso, short-iso-precise, short-full,\n"
354 " short-monotonic, short-unix, verbose, export,\n"
355 " json, json-pretty, json-sse, json-seq, cat,\n"
357 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
358 " -n --lines[=INTEGER] Number of journal entries to show\n"
359 " -r --reverse Show the newest entries first\n"
360 " --show-cursor Print the cursor after all the entries\n"
361 " --utc Express time in Coordinated Universal Time (UTC)\n"
362 " -x --catalog Add message explanations where available\n"
363 " --no-hostname Suppress output of hostname field\n"
364 " --no-full Ellipsize fields\n"
365 " -a --all Show all fields, including long and unprintable\n"
366 " -f --follow Follow the journal\n"
367 " --no-tail Show all lines, even in follow mode\n"
368 " -q --quiet Do not show info messages and privilege warning\n"
369 "\n%3$sPager Control Options:%4$s\n"
370 " --no-pager Do not pipe output into a pager\n"
371 " -e --pager-end Immediately jump to the end in the pager\n"
372 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
373 " --interval=TIME Time interval for changing the FSS sealing key\n"
374 " --verify-key=KEY Specify FSS verification key\n"
375 " --force Override of the FSS key pair with --setup-keys\n"
376 "\n%3$sCommands:%4$s\n"
377 " -h --help Show this help text\n"
378 " --version Show package version\n"
379 " -N --fields List all field names currently used\n"
380 " -F --field=FIELD List all values that a specified field takes\n"
381 " --list-boots Show terse information about recorded boots\n"
382 " --disk-usage Show total disk usage of all journal files\n"
383 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
384 " --vacuum-files=INT Leave only the specified number of journal files\n"
385 " --vacuum-time=TIME Remove journal files older than specified time\n"
386 " --verify Verify journal file consistency\n"
387 " --sync Synchronize unwritten journal messages to disk\n"
388 " --relinquish-var Stop logging to disk, log to temporary file system\n"
389 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
390 " --flush Flush all journal data from /run into /var\n"
391 " --rotate Request immediate rotation of the journal files\n"
392 " --header Show journal header information\n"
393 " --list-catalog Show all message IDs in the catalog\n"
394 " --dump-catalog Show entries in the message catalog\n"
395 " --update-catalog Update the message catalog database\n"
396 " --setup-keys Generate a new FSS key pair\n"
397 "\nSee the %2$s for details.\n",
398 program_invocation_short_name
,
408 static int parse_argv(int argc
, char *argv
[]) {
444 ARG_SMART_RELINQUISH_VAR
,
454 static const struct option options
[] = {
455 { "help", no_argument
, NULL
, 'h' },
456 { "version" , no_argument
, NULL
, ARG_VERSION
},
457 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
458 { "pager-end", no_argument
, NULL
, 'e' },
459 { "follow", no_argument
, NULL
, 'f' },
460 { "force", no_argument
, NULL
, ARG_FORCE
},
461 { "output", required_argument
, NULL
, 'o' },
462 { "all", no_argument
, NULL
, 'a' },
463 { "full", no_argument
, NULL
, 'l' },
464 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
465 { "lines", optional_argument
, NULL
, 'n' },
466 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
467 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
468 { "quiet", no_argument
, NULL
, 'q' },
469 { "merge", no_argument
, NULL
, 'm' },
470 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
471 { "boot", optional_argument
, NULL
, 'b' },
472 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
473 { "dmesg", no_argument
, NULL
, 'k' },
474 { "system", no_argument
, NULL
, ARG_SYSTEM
},
475 { "user", no_argument
, NULL
, ARG_USER
},
476 { "directory", required_argument
, NULL
, 'D' },
477 { "file", required_argument
, NULL
, ARG_FILE
},
478 { "root", required_argument
, NULL
, ARG_ROOT
},
479 { "image", required_argument
, NULL
, ARG_IMAGE
},
480 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
481 { "header", no_argument
, NULL
, ARG_HEADER
},
482 { "identifier", required_argument
, NULL
, 't' },
483 { "priority", required_argument
, NULL
, 'p' },
484 { "facility", required_argument
, NULL
, ARG_FACILITY
},
485 { "grep", required_argument
, NULL
, 'g' },
486 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
487 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
488 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
489 { "verify", no_argument
, NULL
, ARG_VERIFY
},
490 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
491 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
492 { "cursor", required_argument
, NULL
, 'c' },
493 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
494 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
495 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
496 { "since", required_argument
, NULL
, 'S' },
497 { "until", required_argument
, NULL
, 'U' },
498 { "unit", required_argument
, NULL
, 'u' },
499 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
500 { "field", required_argument
, NULL
, 'F' },
501 { "fields", no_argument
, NULL
, 'N' },
502 { "catalog", no_argument
, NULL
, 'x' },
503 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
504 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
505 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
506 { "reverse", no_argument
, NULL
, 'r' },
507 { "machine", required_argument
, NULL
, 'M' },
508 { "utc", no_argument
, NULL
, ARG_UTC
},
509 { "flush", no_argument
, NULL
, ARG_FLUSH
},
510 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
511 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
512 { "sync", no_argument
, NULL
, ARG_SYNC
},
513 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
514 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
515 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
516 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
517 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
518 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
519 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
528 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
539 arg_pager_flags
|= PAGER_DISABLE
;
543 arg_pager_flags
|= PAGER_JUMP_TO_END
;
545 if (arg_lines
== ARG_LINES_DEFAULT
)
556 arg_boot_id
= SD_ID128_NULL
;
562 if (streq(optarg
, "help")) {
563 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
567 arg_output
= output_mode_from_string(optarg
);
569 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
571 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
574 if (OUTPUT_MODE_IS_JSON(arg_output
))
575 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
577 arg_json_format_flags
= JSON_FORMAT_OFF
;
595 if (streq(optarg
, "all"))
596 arg_lines
= ARG_LINES_ALL
;
598 r
= safe_atoi(optarg
, &arg_lines
);
599 if (r
< 0 || arg_lines
< 0)
600 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
605 /* Hmm, no argument? Maybe the next
606 * word on the command line is
607 * supposed to be the argument? Let's
608 * see if there is one, and is
612 if (streq(argv
[optind
], "all")) {
613 arg_lines
= ARG_LINES_ALL
;
615 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
629 arg_action
= ACTION_NEW_ID128
;
642 arg_boot_id
= SD_ID128_NULL
;
648 arg_boot_id
= SD_ID128_NULL
;
652 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
654 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
658 /* Hmm, no argument? Maybe the next
659 * word on the command line is
660 * supposed to be the argument? Let's
661 * see if there is one and is parsable
662 * as a boot descriptor... */
663 } else if (optind
< argc
) {
664 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
673 arg_action
= ACTION_LIST_BOOTS
;
677 arg_boot
= arg_dmesg
= true;
681 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
685 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
689 arg_machine
= optarg
;
693 if (streq(optarg
, "*")) {
694 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
695 arg_namespace
= NULL
;
696 } else if (startswith(optarg
, "+")) {
697 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
698 arg_namespace
= optarg
+ 1;
699 } else if (isempty(optarg
)) {
700 arg_namespace_flags
= 0;
701 arg_namespace
= NULL
;
703 arg_namespace_flags
= 0;
704 arg_namespace
= optarg
;
710 arg_directory
= optarg
;
714 if (streq(optarg
, "-"))
715 /* An undocumented feature: we can read journal files from STDIN. We don't document
716 * this though, since after all we only support this for mmap-able, seekable files, and
717 * not for example pipes which are probably the primary usecase for reading things from
718 * STDIN. To avoid confusion we hence don't document this feature. */
719 arg_file_stdin
= true;
721 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
723 return log_error_errno(r
, "Failed to add paths: %m");
728 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
734 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
739 case ARG_IMAGE_POLICY
:
740 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
749 case ARG_CURSOR_FILE
:
750 arg_cursor_file
= optarg
;
753 case ARG_AFTER_CURSOR
:
754 arg_after_cursor
= optarg
;
757 case ARG_SHOW_CURSOR
:
758 arg_show_cursor
= true;
762 arg_action
= ACTION_PRINT_HEADER
;
766 arg_action
= ACTION_VERIFY
;
770 arg_action
= ACTION_DISK_USAGE
;
773 case ARG_VACUUM_SIZE
:
774 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
776 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
778 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
781 case ARG_VACUUM_FILES
:
782 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
784 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
786 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
789 case ARG_VACUUM_TIME
:
790 r
= parse_sec(optarg
, &arg_vacuum_time
);
792 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
794 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
803 arg_action
= ACTION_SETUP_KEYS
;
807 r
= free_and_strdup(&arg_verify_key
, optarg
);
810 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
811 * in ps or htop output. */
812 memset(optarg
, 'x', strlen(optarg
));
814 arg_action
= ACTION_VERIFY
;
819 r
= parse_sec(optarg
, &arg_interval
);
820 if (r
< 0 || arg_interval
<= 0)
821 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
822 "Failed to parse sealing key change interval: %s", optarg
);
829 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
830 "Compiled without forward-secure sealing support.");
836 dots
= strstr(optarg
, "..");
838 _cleanup_free_
char *a
= NULL
;
842 a
= strndup(optarg
, dots
- optarg
);
846 from
= log_level_from_string(a
);
847 to
= log_level_from_string(dots
+ 2);
849 if (from
< 0 || to
< 0)
850 return log_error_errno(from
< 0 ? from
: to
,
851 "Failed to parse log level range %s", optarg
);
856 for (i
= from
; i
<= to
; i
++)
857 arg_priorities
|= 1 << i
;
859 for (i
= to
; i
<= from
; i
++)
860 arg_priorities
|= 1 << i
;
866 p
= log_level_from_string(optarg
);
868 return log_error_errno(p
, "Unknown log level %s", optarg
);
872 for (i
= 0; i
<= p
; i
++)
873 arg_priorities
|= 1 << i
;
883 _cleanup_free_
char *fac
= NULL
;
886 r
= extract_first_word(&p
, &fac
, ",", 0);
888 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
892 if (streq(fac
, "help")) {
897 num
= log_facility_unshifted_from_string(fac
);
899 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
901 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
909 arg_pattern
= optarg
;
912 case ARG_CASE_SENSITIVE
:
914 r
= parse_boolean(optarg
);
916 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
917 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
919 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
924 r
= parse_timestamp(optarg
, &arg_since
);
926 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
927 "Failed to parse timestamp: %s", optarg
);
928 arg_since_set
= true;
932 r
= parse_timestamp(optarg
, &arg_until
);
934 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
935 "Failed to parse timestamp: %s", optarg
);
936 arg_until_set
= true;
940 r
= strv_extend(&arg_syslog_identifier
, optarg
);
946 r
= strv_extend(&arg_system_units
, optarg
);
952 r
= strv_extend(&arg_user_units
, optarg
);
958 arg_action
= ACTION_LIST_FIELDS
;
963 arg_action
= ACTION_LIST_FIELD_NAMES
;
966 case ARG_NO_HOSTNAME
:
967 arg_no_hostname
= true;
974 case ARG_LIST_CATALOG
:
975 arg_action
= ACTION_LIST_CATALOG
;
978 case ARG_DUMP_CATALOG
:
979 arg_action
= ACTION_DUMP_CATALOG
;
982 case ARG_UPDATE_CATALOG
:
983 arg_action
= ACTION_UPDATE_CATALOG
;
995 arg_action
= ACTION_FLUSH
;
998 case ARG_SMART_RELINQUISH_VAR
: {
999 int root_mnt_id
, log_mnt_id
;
1001 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
1002 * if it's on the same mount as the root file system there's no point in
1003 * relinquishing access and we can leave journald write to it until the very last
1006 r
= path_get_mnt_id("/", &root_mnt_id
);
1008 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1010 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1012 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1013 else if (root_mnt_id
== log_mnt_id
) {
1014 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1017 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1023 case ARG_RELINQUISH_VAR
:
1024 arg_action
= ACTION_RELINQUISH_VAR
;
1028 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1032 arg_action
= ACTION_SYNC
;
1035 case ARG_OUTPUT_FIELDS
: {
1036 _cleanup_strv_free_
char **v
= NULL
;
1038 v
= strv_split(optarg
, ",");
1042 r
= set_put_strdupv(&arg_output_fields
, v
);
1052 assert_not_reached();
1055 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
1058 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1059 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1060 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1062 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1063 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1064 "--since= must be before --until=.");
1066 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1067 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1068 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1070 if (arg_follow
&& arg_reverse
)
1071 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1072 "Please specify either --reverse= or --follow=, not both.");
1074 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1075 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1076 "Extraneous arguments starting with '%s'",
1079 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1080 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1081 "Using --boot or --list-boots with --merge is not supported.");
1083 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1084 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1085 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1086 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1087 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1091 arg_system_units
= strv_free(arg_system_units
);
1095 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1099 /* When --grep is used along with --lines, we don't know how many lines we can print.
1100 * So we search backwards and count until enough lines have been printed or we hit the head.
1101 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1102 * if that is specified. */
1103 if (arg_lines
>= 0 && !arg_follow
)
1110 static int add_matches(sd_journal
*j
, char **args
) {
1111 bool have_term
= false;
1115 STRV_FOREACH(i
, args
) {
1118 if (streq(*i
, "+")) {
1121 r
= sd_journal_add_disjunction(j
);
1124 } else if (path_is_absolute(*i
)) {
1125 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1128 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1130 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1132 if (lstat(p
, &st
) < 0)
1133 return log_error_errno(errno
, "Couldn't stat file: %m");
1135 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1136 if (executable_is_script(p
, &interpreter
) > 0) {
1137 _cleanup_free_
char *comm
= NULL
;
1139 r
= path_extract_filename(p
, &comm
);
1141 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1143 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1147 /* Append _EXE only if the interpreter is not a link.
1148 Otherwise, it might be outdated often. */
1149 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1150 t2
= strjoin("_EXE=", interpreter
);
1155 t
= strjoin("_EXE=", p
);
1160 r
= sd_journal_add_match(j
, t
, 0);
1163 r
= sd_journal_add_match(j
, t2
, 0);
1165 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1166 r
= add_matches_for_device(j
, p
);
1170 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1171 "File is neither a device node, nor regular file, nor executable: %s",
1176 r
= sd_journal_add_match(j
, *i
, 0);
1181 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1184 if (!strv_isempty(args
) && !have_term
)
1185 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1186 "\"+\" can only be used between terms");
1191 static void boot_id_free_all(BootId
*l
) {
1195 LIST_REMOVE(boot_list
, l
, i
);
1200 static int discover_next_boot(sd_journal
*j
,
1201 sd_id128_t previous_boot_id
,
1205 _cleanup_free_ BootId
*next_boot
= NULL
;
1206 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1213 /* We expect the journal to be on the last position of a boot
1214 * (in relation to the direction we are going), so that the next
1215 * invocation of sd_journal_next/previous will be from a different
1216 * boot. We then collect any information we desire and then jump
1217 * to the last location of the new boot by using a _BOOT_ID match
1218 * coming from the other journal direction. */
1220 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1221 * we can actually advance to a *different* boot. */
1222 sd_journal_flush_matches(j
);
1226 r
= sd_journal_previous(j
);
1228 r
= sd_journal_next(j
);
1232 return 0; /* End of journal, yay. */
1234 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1238 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1239 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1240 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1241 * complete than the main entry array, and hence might reference an entry that's not actually the last
1242 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1243 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1246 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1248 next_boot
= new0(BootId
, 1);
1252 next_boot
->id
= boot_id
;
1254 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1258 /* Now seek to the last occurrence of this boot ID. */
1259 sd_id128_to_string(next_boot
->id
, match
+ STRLEN("_BOOT_ID="));
1260 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1265 r
= sd_journal_seek_head(j
);
1267 r
= sd_journal_seek_tail(j
);
1272 r
= sd_journal_next(j
);
1274 r
= sd_journal_previous(j
);
1278 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1279 "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. */
1281 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1285 *ret
= TAKE_PTR(next_boot
);
1290 static int get_boots(
1293 sd_id128_t
*boot_id
,
1298 BootId
*head
= NULL
, *tail
= NULL
;
1299 const bool advance_older
= boot_id
&& offset
<= 0;
1300 sd_id128_t previous_boot_id
;
1304 /* Adjust for the asymmetry that offset 0 is
1305 * the last (and current) boot, while 1 is considered the
1306 * (chronological) first boot in the journal. */
1307 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1309 /* Advance to the earliest/latest occurrence of our reference
1310 * boot ID (taking our lookup direction into account), so that
1311 * discover_next_boot() can do its job.
1312 * If no reference is given, the journal head/tail will do,
1313 * they're "virtual" boots after all. */
1314 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1315 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1317 sd_journal_flush_matches(j
);
1319 sd_id128_to_string(*boot_id
, match
+ STRLEN("_BOOT_ID="));
1320 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1325 r
= sd_journal_seek_head(j
); /* seek to oldest */
1327 r
= sd_journal_seek_tail(j
); /* seek to newest */
1332 r
= sd_journal_next(j
); /* read the oldest entry */
1334 r
= sd_journal_previous(j
); /* read the most recently added entry */
1339 else if (offset
== 0) {
1344 /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot
1345 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1346 * the following entry, which must then have an older/newer boot ID */
1350 r
= sd_journal_seek_tail(j
); /* seek to newest */
1352 r
= sd_journal_seek_head(j
); /* seek to oldest */
1356 /* No sd_journal_next()/_previous() here.
1358 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1359 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1363 previous_boot_id
= SD_ID128_NULL
;
1365 _cleanup_free_ BootId
*current
= NULL
;
1367 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1369 boot_id_free_all(head
);
1376 previous_boot_id
= current
->id
;
1380 offset
+= advance_older
? 1 : -1;
1385 *boot_id
= current
->id
;
1389 LIST_FOREACH(boot_list
, id
, head
) {
1390 if (sd_id128_equal(id
->id
, current
->id
)) {
1391 /* boot id already stored, something wrong with the journal files */
1392 /* exiting as otherwise this problem would cause forever loop */
1396 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1397 tail
= TAKE_PTR(current
);
1406 sd_journal_flush_matches(j
);
1411 static int list_boots(sd_journal
*j
) {
1412 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1418 count
= get_boots(j
, &all_ids
, NULL
, 0);
1420 return log_error_errno(count
, "Failed to determine boots: %m");
1424 table
= table_new("idx", "boot id", "first entry", "last entry");
1429 table_set_width(table
, 0);
1431 r
= table_set_json_field_name(table
, 0, "index");
1433 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1435 (void) table_set_sort(table
, (size_t) 0);
1436 (void) table_set_reverse(table
, 0, arg_reverse
);
1439 LIST_FOREACH(boot_list
, id
, all_ids
) {
1440 r
= table_add_many(table
,
1441 TABLE_INT
, i
- count
+ 1,
1442 TABLE_SET_ALIGN_PERCENT
, 100,
1443 TABLE_ID128
, id
->id
,
1444 TABLE_TIMESTAMP
, id
->first
,
1445 TABLE_TIMESTAMP
, id
->last
);
1447 return table_log_add_error(r
);
1451 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1453 return table_log_print_error(r
);
1455 boot_id_free_all(all_ids
);
1460 static int add_boot(sd_journal
*j
) {
1461 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1470 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1471 * We can do this only when we logs are coming from the current machine,
1472 * so take the slow path if log location is specified. */
1473 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1474 !arg_directory
&& !arg_file
&& !arg_root
)
1475 return add_match_this_boot(j
, arg_machine
);
1477 boot_id
= arg_boot_id
;
1478 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1481 const char *reason
= (r
== 0) ? "No such boot ID in journal" : STRERROR(r
);
1483 if (sd_id128_is_null(arg_boot_id
))
1484 log_error("Data from the specified boot (%+i) is not available: %s",
1485 arg_boot_offset
, reason
);
1487 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1488 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1490 return r
== 0 ? -ENODATA
: r
;
1493 sd_id128_to_string(boot_id
, match
+ STRLEN("_BOOT_ID="));
1495 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1497 return log_error_errno(r
, "Failed to add match: %m");
1499 r
= sd_journal_add_conjunction(j
);
1501 return log_error_errno(r
, "Failed to add conjunction: %m");
1506 static int add_dmesg(sd_journal
*j
) {
1513 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1514 STRLEN("_TRANSPORT=kernel"));
1516 return log_error_errno(r
, "Failed to add match: %m");
1518 r
= sd_journal_add_conjunction(j
);
1520 return log_error_errno(r
, "Failed to add conjunction: %m");
1525 static int get_possible_units(
1531 _cleanup_set_free_free_ Set
*found
= NULL
;
1534 found
= set_new(&string_hash_ops
);
1538 NULSTR_FOREACH(field
, fields
) {
1542 r
= sd_journal_query_unique(j
, field
);
1546 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1549 _cleanup_free_
char *u
= NULL
;
1551 eq
= memchr(data
, '=', size
);
1553 prefix
= eq
- (char*) data
+ 1;
1557 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1561 STRV_FOREACH(pattern
, patterns
)
1562 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1563 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1565 r
= set_consume(found
, u
);
1567 if (r
< 0 && r
!= -EEXIST
)
1575 *units
= TAKE_PTR(found
);
1580 /* This list is supposed to return the superset of unit names
1581 * possibly matched by rules added with add_matches_for_unit... */
1582 #define SYSTEM_UNITS \
1586 "OBJECT_SYSTEMD_UNIT\0" \
1589 /* ... and add_matches_for_user_unit */
1590 #define USER_UNITS \
1591 "_SYSTEMD_USER_UNIT\0" \
1593 "COREDUMP_USER_UNIT\0" \
1594 "OBJECT_SYSTEMD_USER_UNIT\0" \
1595 "_SYSTEMD_USER_SLICE\0"
1597 static int add_units(sd_journal
*j
) {
1598 _cleanup_strv_free_
char **patterns
= NULL
;
1603 STRV_FOREACH(i
, arg_system_units
) {
1604 _cleanup_free_
char *u
= NULL
;
1606 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1610 if (string_is_glob(u
)) {
1611 r
= strv_push(&patterns
, u
);
1616 r
= add_matches_for_unit(j
, u
);
1619 r
= sd_journal_add_disjunction(j
);
1626 if (!strv_isempty(patterns
)) {
1627 _cleanup_set_free_free_ Set
*units
= NULL
;
1630 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1634 SET_FOREACH(u
, units
) {
1635 r
= add_matches_for_unit(j
, u
);
1638 r
= sd_journal_add_disjunction(j
);
1645 patterns
= strv_free(patterns
);
1647 STRV_FOREACH(i
, arg_user_units
) {
1648 _cleanup_free_
char *u
= NULL
;
1650 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1654 if (string_is_glob(u
)) {
1655 r
= strv_push(&patterns
, u
);
1660 r
= add_matches_for_user_unit(j
, u
, getuid());
1663 r
= sd_journal_add_disjunction(j
);
1670 if (!strv_isempty(patterns
)) {
1671 _cleanup_set_free_free_ Set
*units
= NULL
;
1674 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1678 SET_FOREACH(u
, units
) {
1679 r
= add_matches_for_user_unit(j
, u
, getuid());
1682 r
= sd_journal_add_disjunction(j
);
1689 /* Complain if the user request matches but nothing whatsoever was
1690 * found, since otherwise everything would be matched. */
1691 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1694 r
= sd_journal_add_conjunction(j
);
1701 static int add_priorities(sd_journal
*j
) {
1702 char match
[] = "PRIORITY=0";
1706 if (arg_priorities
== 0xFF)
1709 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1710 if (arg_priorities
& (1 << i
)) {
1711 match
[sizeof(match
)-2] = '0' + i
;
1713 r
= sd_journal_add_match(j
, match
, strlen(match
));
1715 return log_error_errno(r
, "Failed to add match: %m");
1718 r
= sd_journal_add_conjunction(j
);
1720 return log_error_errno(r
, "Failed to add conjunction: %m");
1725 static int add_facilities(sd_journal
*j
) {
1729 SET_FOREACH(p
, arg_facilities
) {
1730 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1732 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1734 r
= sd_journal_add_match(j
, match
, strlen(match
));
1736 return log_error_errno(r
, "Failed to add match: %m");
1742 static int add_syslog_identifier(sd_journal
*j
) {
1747 STRV_FOREACH(i
, arg_syslog_identifier
) {
1748 _cleanup_free_
char *u
= NULL
;
1750 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1753 r
= sd_journal_add_match(j
, u
, 0);
1756 r
= sd_journal_add_disjunction(j
);
1761 r
= sd_journal_add_conjunction(j
);
1769 static int format_journal_url(
1778 _cleanup_free_
char *url
= NULL
;
1779 _cleanup_fclose_
FILE *f
= NULL
;
1780 size_t url_size
= 0;
1784 assert(seed_size
> 0);
1786 f
= open_memstream_unlocked(&url
, &url_size
);
1793 for (size_t i
= 0; i
< seed_size
; i
++) {
1794 if (i
> 0 && i
% 3 == 0)
1796 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1799 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1802 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1804 fprintf(f
, ";hostname=%s", hn
);
1807 r
= fflush_and_check(f
);
1812 *ret_url
= TAKE_PTR(url
);
1817 static int setup_keys(void) {
1819 size_t mpk_size
, seed_size
, state_size
;
1820 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1821 _cleanup_free_
char *p
= NULL
;
1822 uint8_t *mpk
, *seed
, *state
;
1823 _cleanup_close_
int fd
= -EBADF
;
1824 sd_id128_t machine
, boot
;
1829 r
= stat("/var/log/journal", &st
);
1830 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1831 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1833 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1834 log_error("%s is not a directory, must be using persistent logging for FSS.",
1835 "/var/log/journal");
1836 return r
< 0 ? -errno
: -ENOTDIR
;
1839 r
= sd_id128_get_machine(&machine
);
1841 return log_error_errno(r
, "Failed to get machine ID: %m");
1843 r
= sd_id128_get_boot(&boot
);
1845 return log_error_errno(r
, "Failed to get boot ID: %m");
1847 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1848 SD_ID128_FORMAT_VAL(machine
)) < 0)
1853 if (r
< 0 && errno
!= ENOENT
)
1854 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1855 } else if (access(p
, F_OK
) >= 0)
1856 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1857 "Sealing key file %s exists already. Use --force to recreate.", p
);
1859 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1860 SD_ID128_FORMAT_VAL(machine
)) < 0)
1863 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1864 mpk
= alloca_safe(mpk_size
);
1866 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1867 seed
= alloca_safe(seed_size
);
1869 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1870 state
= alloca_safe(state_size
);
1872 log_info("Generating seed...");
1873 r
= crypto_random_bytes(seed
, seed_size
);
1875 return log_error_errno(r
, "Failed to acquire random seed: %m");
1877 log_info("Generating key pair...");
1878 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1880 log_info("Generating sealing key...");
1881 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1883 assert(arg_interval
> 0);
1885 n
= now(CLOCK_REALTIME
);
1889 fd
= mkostemp_safe(k
);
1891 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1893 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1895 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1896 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1898 struct FSSHeader h
= {
1899 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1900 .machine_id
= machine
,
1902 .header_size
= htole64(sizeof(h
)),
1903 .start_usec
= htole64(n
* arg_interval
),
1904 .interval_usec
= htole64(arg_interval
),
1905 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1906 .fsprg_state_size
= htole64(state_size
),
1909 r
= loop_write(fd
, &h
, sizeof(h
), false);
1911 return log_error_errno(r
, "Failed to write header: %m");
1913 r
= loop_write(fd
, state
, state_size
, false);
1915 return log_error_errno(r
, "Failed to write state: %m");
1917 if (rename(k
, p
) < 0)
1918 return log_error_errno(errno
, "Failed to link file: %m");
1922 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1924 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1929 hn
= gethostname_malloc();
1931 hostname_cleanup(hn
);
1934 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1936 "The %ssecret sealing key%s has been written to the following local file.\n"
1937 "This key file is automatically updated when the sealing key is advanced.\n"
1938 "It should not be used on multiple hosts.\n"
1942 "The sealing key is automatically changed every %s.\n"
1944 "Please write down the following %ssecret verification key%s. It should be stored\n"
1945 "in a safe location and should not be saved locally on disk.\n"
1947 strempty(hn
), hn
? "/" : "",
1948 SD_ID128_FORMAT_VAL(machine
),
1949 ansi_highlight(), ansi_normal(),
1951 FORMAT_TIMESPAN(arg_interval
, 0),
1952 ansi_highlight(), ansi_normal(),
1953 ansi_highlight_red());
1960 fprintf(stderr
, "%s", ansi_normal());
1962 _cleanup_free_
char *url
= NULL
;
1963 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1967 (void) print_qrcode(stderr
,
1968 "To transfer the verification key to your phone scan the QR code below",
1975 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1976 "Forward-secure sealing not available.");
1980 static int verify(sd_journal
*j
, bool verbose
) {
1986 log_show_color(true);
1988 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1990 usec_t first
= 0, validated
= 0, last
= 0;
1993 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1994 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1997 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1999 /* If the key was invalid give up right-away. */
2002 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
2004 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
2005 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
2007 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
2008 if (validated
> 0) {
2009 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2010 "=> Validated from %s to %s, final %s entries not sealed.",
2011 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
2012 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
2013 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
2014 } else if (last
> 0)
2015 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2016 "=> No sealing yet, %s of entries not sealed.",
2017 FORMAT_TIMESPAN(last
- first
, 0));
2019 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2020 "=> No sealing yet, no entries in file.");
2028 static int simple_varlink_call(const char *option
, const char *method
) {
2029 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2030 const char *error
, *fn
;
2034 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2036 fn
= arg_namespace
?
2037 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2038 "/run/systemd/journal/io.systemd.journal";
2040 r
= varlink_connect_address(&link
, fn
);
2042 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2044 (void) varlink_set_description(link
, "journal");
2045 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2047 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2049 return log_error_errno(r
, "Failed to execute varlink call: %m");
2051 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2052 "Failed to execute varlink call: %s", error
);
2057 static int flush_to_var(void) {
2058 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2059 return 0; /* Already flushed, no need to contact journald */
2060 if (errno
!= ENOENT
)
2061 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2063 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2066 static int relinquish_var(void) {
2067 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2070 static int rotate(void) {
2071 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2074 static int sync_journal(void) {
2075 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2078 static int wait_for_change(sd_journal
*j
, int poll_fd
) {
2079 struct pollfd pollfds
[] = {
2080 { .fd
= poll_fd
, .events
= POLLIN
},
2081 { .fd
= STDOUT_FILENO
},
2087 assert(poll_fd
>= 0);
2089 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
2090 * i.e. when it is closed. */
2092 r
= sd_journal_get_timeout(j
, &timeout
);
2094 return log_error_errno(r
, "Failed to determine journal waiting time: %m");
2096 r
= ppoll_usec(pollfds
, ELEMENTSOF(pollfds
), timeout
);
2100 return log_error_errno(r
, "Couldn't wait for journal event: %m");
2102 if (pollfds
[1].revents
& (POLLHUP
|POLLERR
)) /* STDOUT has been closed? */
2103 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
),
2104 "Standard output has been closed.");
2106 r
= sd_journal_process(j
);
2108 return log_error_errno(r
, "Failed to process journal events: %m");
2113 static int run(int argc
, char *argv
[]) {
2114 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2115 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2116 bool previous_boot_id_valid
= false, first_line
= true, ellipsized
= false, need_seek
= false, since_seeked
= false;
2117 bool use_cursor
= false, after_cursor
= false;
2118 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2119 sd_id128_t previous_boot_id
= SD_ID128_NULL
, previous_boot_id_output
= SD_ID128_NULL
;
2120 dual_timestamp previous_ts_output
= DUAL_TIMESTAMP_NULL
;
2121 _cleanup_close_
int machine_fd
= -EBADF
;
2122 int n_shown
= 0, r
, poll_fd
= -EBADF
;
2124 setlocale(LC_ALL
, "");
2127 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2128 * split up into many files. */
2129 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2131 r
= parse_argv(argc
, argv
);
2138 r
= mount_image_privately_interactively(
2141 DISSECT_IMAGE_GENERIC_ROOT
|
2142 DISSECT_IMAGE_REQUIRE_ROOT
|
2143 DISSECT_IMAGE_VALIDATE_OS
|
2144 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2145 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2147 /* ret_dir_fd= */ NULL
,
2152 arg_root
= strdup(mounted_dir
);
2157 signal(SIGWINCH
, columns_lines_cache_reset
);
2160 switch (arg_action
) {
2162 case ACTION_NEW_ID128
:
2163 return id128_print_new(ID128_PRINT_PRETTY
);
2165 case ACTION_SETUP_KEYS
:
2166 return setup_keys();
2168 case ACTION_LIST_CATALOG
:
2169 case ACTION_DUMP_CATALOG
:
2170 case ACTION_UPDATE_CATALOG
: {
2171 _cleanup_free_
char *database
= NULL
;
2173 database
= path_join(arg_root
, CATALOG_DATABASE
);
2177 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2178 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2180 return log_error_errno(r
, "Failed to list catalog: %m");
2182 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2184 pager_open(arg_pager_flags
);
2187 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2189 r
= catalog_list(stdout
, database
, oneline
);
2191 return log_error_errno(r
, "Failed to list catalog: %m");
2198 return flush_to_var();
2200 case ACTION_RELINQUISH_VAR
:
2201 return relinquish_var();
2204 return sync_journal();
2210 case ACTION_PRINT_HEADER
:
2212 case ACTION_DISK_USAGE
:
2213 case ACTION_LIST_BOOTS
:
2215 case ACTION_ROTATE_AND_VACUUM
:
2216 case ACTION_LIST_FIELDS
:
2217 case ACTION_LIST_FIELD_NAMES
:
2218 /* These ones require access to the journal files, continue below. */
2222 assert_not_reached();
2226 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2228 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2229 else if (arg_file_stdin
)
2230 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2232 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2233 else if (arg_machine
) {
2234 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2235 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2236 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2240 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2241 * the container, thus we need root privileges to override them. */
2242 return log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2244 r
= sd_bus_open_system(&bus
);
2246 return log_error_errno(r
, "Failed to open system bus: %m");
2248 r
= sd_bus_call_method(
2250 "org.freedesktop.machine1",
2251 "/org/freedesktop/machine1",
2252 "org.freedesktop.machine1.Manager",
2253 "OpenMachineRootDirectory",
2258 return log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2260 r
= sd_bus_message_read(reply
, "h", &fd
);
2262 return bus_log_parse_error(r
);
2264 machine_fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2266 return log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2268 r
= sd_journal_open_directory_fd(&j
, machine_fd
, SD_JOURNAL_OS_ROOT
);
2270 r
= sd_journal_open_namespace(
2273 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2274 arg_namespace_flags
| arg_journal_type
);
2276 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2278 r
= journal_access_check_and_warn(j
, arg_quiet
,
2279 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2283 switch (arg_action
) {
2285 case ACTION_NEW_ID128
:
2286 case ACTION_SETUP_KEYS
:
2287 case ACTION_LIST_CATALOG
:
2288 case ACTION_DUMP_CATALOG
:
2289 case ACTION_UPDATE_CATALOG
:
2293 assert_not_reached();
2295 case ACTION_PRINT_HEADER
:
2296 journal_print_header(j
);
2300 return verify(j
, !arg_quiet
);
2302 case ACTION_DISK_USAGE
: {
2305 r
= sd_journal_get_usage(j
, &bytes
);
2309 printf("Archived and active journals take up %s in the file system.\n",
2310 FORMAT_BYTES(bytes
));
2315 case ACTION_LIST_BOOTS
:
2316 return list_boots(j
);
2318 case ACTION_ROTATE_AND_VACUUM
:
2326 case ACTION_VACUUM
: {
2330 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2331 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2333 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2342 case ACTION_LIST_FIELD_NAMES
: {
2345 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2346 printf("%s\n", field
);
2352 case ACTION_LIST_FIELDS
:
2356 assert_not_reached();
2359 if (arg_boot_offset
!= 0 &&
2360 sd_journal_has_runtime_files(j
) > 0 &&
2361 sd_journal_has_persistent_files(j
) == 0) {
2362 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2364 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2369 /* add_boot() must be called first!
2370 * It may need to seek the journal to find parent boot IDs. */
2381 return log_error_errno(r
, "Failed to add filter for units: %m");
2383 r
= add_syslog_identifier(j
);
2385 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2387 r
= add_priorities(j
);
2391 r
= add_facilities(j
);
2395 r
= add_matches(j
, argv
+ optind
);
2399 if (DEBUG_LOGGING
) {
2400 _cleanup_free_
char *filter
= NULL
;
2402 filter
= journal_make_match_string(j
);
2406 log_debug("Journal filter: %s", filter
);
2409 if (arg_action
== ACTION_LIST_FIELDS
) {
2415 r
= sd_journal_set_data_threshold(j
, 0);
2417 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2419 r
= sd_journal_query_unique(j
, arg_field
);
2421 return log_error_errno(r
, "Failed to query unique data objects: %m");
2423 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2426 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2429 eq
= memchr(data
, '=', size
);
2431 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2433 printf("%.*s\n", (int) size
, (const char*) data
);
2441 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2443 poll_fd
= sd_journal_get_fd(j
);
2444 if (poll_fd
== -EMFILE
) {
2445 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2447 } else if (poll_fd
== -EMEDIUMTYPE
)
2448 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2449 else if (poll_fd
< 0)
2450 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2453 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2454 _cleanup_free_
char *cursor_from_file
= NULL
;
2455 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2457 if (arg_cursor_file
) {
2458 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2459 if (r
< 0 && r
!= -ENOENT
)
2460 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2463 cursor
= cursor_from_file
;
2464 after_cursor
= true;
2467 after_cursor
= arg_after_cursor
;
2470 r
= sd_journal_seek_cursor(j
, cursor
);
2472 return log_error_errno(r
, "Failed to seek to cursor: %m");
2480 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2482 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2484 if (after_cursor
&& r
< 2) {
2485 /* We couldn't find the next entry after the cursor. */
2492 } else if (arg_until_set
&& (arg_reverse
|| arg_lines
>= 0)) {
2493 /* If both --until and any of --reverse and --lines is specified, things get
2494 * a little tricky. We seek to the place of --until first. If only --reverse or
2495 * --reverse and --lines is specified, we search backwards and let the output
2496 * counter handle --lines for us. If only --lines is used, we just jump backwards
2497 * arg_lines and search afterwards from there. */
2499 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2501 return log_error_errno(r
, "Failed to seek to date: %m");
2504 r
= sd_journal_previous(j
);
2505 else /* arg_lines >= 0 */
2506 r
= sd_journal_previous_skip(j
, arg_lines
);
2508 } else if (arg_reverse
) {
2509 r
= sd_journal_seek_tail(j
);
2511 return log_error_errno(r
, "Failed to seek to tail: %m");
2513 r
= sd_journal_previous(j
);
2515 } else if (arg_lines
>= 0) {
2516 r
= sd_journal_seek_tail(j
);
2518 return log_error_errno(r
, "Failed to seek to tail: %m");
2520 r
= sd_journal_previous_skip(j
, arg_lines
);
2522 } else if (arg_since_set
) {
2523 /* This is placed after arg_reverse and arg_lines. If --since is used without
2524 * both, we seek to the place of --since and search afterwards from there.
2525 * If used with --reverse or --lines, we seek to the tail first and check if
2526 * the entry is within the range of --since later. */
2528 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2530 return log_error_errno(r
, "Failed to seek to date: %m");
2531 since_seeked
= true;
2533 r
= sd_journal_next(j
);
2536 r
= sd_journal_seek_head(j
);
2538 return log_error_errno(r
, "Failed to seek to head: %m");
2540 r
= sd_journal_next(j
);
2543 return log_error_errno(r
, "Failed to iterate through journal: %m");
2548 pager_open(arg_pager_flags
);
2550 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2552 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2554 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2556 return log_error_errno(r
, "Failed to get cutoff: %m");
2559 printf("-- Journal begins at %s. --\n",
2560 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2562 printf("-- Journal begins at %s, ends at %s. --\n",
2563 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2564 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2569 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2571 size_t highlight
[2] = {};
2575 r
= sd_journal_next(j
);
2577 r
= sd_journal_previous(j
);
2579 return log_error_errno(r
, "Failed to iterate through journal: %m");
2584 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2585 /* If --lines= is set, we usually rely on the n_shown to tell us
2586 * when to stop. However, if --since= is set too, we may end up
2587 * having less than --lines= to output. In this case let's also
2588 * check if the entry is in range. */
2592 r
= sd_journal_get_realtime_usec(j
, &usec
);
2594 return log_error_errno(r
, "Failed to determine timestamp: %m");
2595 if (usec
> arg_until
)
2599 if (arg_since_set
&& (arg_reverse
|| !since_seeked
)) {
2602 r
= sd_journal_get_realtime_usec(j
, &usec
);
2604 return log_error_errno(r
, "Failed to determine timestamp: %m");
2606 if (usec
< arg_since
) {
2608 break; /* Reached the earliest entry */
2610 /* arg_lines >= 0 (!since_seeked):
2611 * We jumped arg_lines back and it seems to be too much */
2612 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2614 return log_error_errno(r
, "Failed to seek to date: %m");
2615 since_seeked
= true;
2620 since_seeked
= true; /* We're surely within the range of --since now */
2623 if (!arg_merge
&& !arg_quiet
) {
2626 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2628 if (previous_boot_id_valid
&&
2629 !sd_id128_equal(boot_id
, previous_boot_id
))
2630 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2631 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2633 previous_boot_id
= boot_id
;
2634 previous_boot_id_valid
= true;
2638 if (arg_compiled_pattern
) {
2639 const void *message
;
2642 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2649 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2652 assert_se(message
= startswith(message
, "MESSAGE="));
2654 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2655 len
- strlen("MESSAGE="), highlight
);
2665 arg_all
* OUTPUT_SHOW_ALL
|
2666 arg_full
* OUTPUT_FULL_WIDTH
|
2667 colors_enabled() * OUTPUT_COLOR
|
2668 arg_catalog
* OUTPUT_CATALOG
|
2669 arg_utc
* OUTPUT_UTC
|
2670 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2672 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2673 arg_output_fields
, highlight
, &ellipsized
,
2674 &previous_ts_output
, &previous_boot_id_output
);
2676 if (r
== -EADDRNOTAVAIL
)
2683 /* If journalctl take a long time to process messages, and during that time journal file
2684 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2685 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2686 * in the "following" case. By periodically calling sd_journal_process() during the processing
2687 * loop we shrink the window of time a client instance has open file descriptors for rotated
2688 * (deleted) journal files. */
2689 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2690 r
= sd_journal_process(j
);
2692 return log_error_errno(r
, "Failed to process inotify events: %m");
2697 if (n_shown
== 0 && !arg_quiet
)
2698 printf("-- No entries --\n");
2704 r
= wait_for_change(j
, poll_fd
);
2711 if (arg_show_cursor
|| arg_cursor_file
) {
2712 _cleanup_free_
char *cursor
= NULL
;
2714 r
= sd_journal_get_cursor(j
, &cursor
);
2715 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2716 return log_error_errno(r
, "Failed to get cursor: %m");
2718 if (arg_show_cursor
)
2719 printf("-- cursor: %s\n", cursor
);
2721 if (arg_cursor_file
) {
2722 r
= write_string_file(arg_cursor_file
, cursor
,
2723 WRITE_STRING_FILE_CREATE
|
2724 WRITE_STRING_FILE_ATOMIC
);
2726 return log_error_errno(r
, "Failed to write new cursor to %s: %m",
2732 if (arg_compiled_pattern
&& n_shown
== 0)
2733 /* --grep was used, no error was thrown, but the pattern didn't
2734 * match anything. Let's mimic grep's behavior here and return
2735 * a non-zero exit code, so journalctl --grep can be used
2736 * in scripts and such */
2742 DEFINE_MAIN_FUNCTION(run
);