1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include <sys/inotify.h>
17 #include "sd-device.h"
18 #include "sd-journal.h"
21 #include "alloc-util.h"
23 #include "bus-error.h"
24 #include "bus-locator.h"
28 #include "chattr-util.h"
29 #include "constants.h"
30 #include "devnum-util.h"
31 #include "dissect-image.h"
34 #include "format-table.h"
35 #include "format-util.h"
38 #include "glob-util.h"
39 #include "hostname-util.h"
40 #include "id128-print.h"
42 #include "journal-def.h"
43 #include "journal-internal.h"
44 #include "journal-util.h"
45 #include "journal-vacuum.h"
46 #include "journal-verify.h"
47 #include "locale-util.h"
49 #include "logs-show.h"
50 #include "main-func.h"
51 #include "memory-util.h"
52 #include "missing_sched.h"
54 #include "mount-util.h"
55 #include "mountpoint-util.h"
56 #include "nulstr-util.h"
58 #include "parse-argument.h"
59 #include "parse-util.h"
60 #include "path-util.h"
61 #include "pcre2-util.h"
62 #include "pretty-print.h"
63 #include "qrcode-util.h"
64 #include "random-util.h"
65 #include "rlimit-util.h"
68 #include "static-destruct.h"
69 #include "stdio-util.h"
70 #include "string-table.h"
72 #include "syslog-util.h"
73 #include "terminal-util.h"
74 #include "tmpfile-util.h"
75 #include "unit-name.h"
76 #include "user-util.h"
79 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
80 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
83 /* Special values for arg_lines */
84 ARG_LINES_DEFAULT
= -2,
88 static OutputMode arg_output
= OUTPUT_SHORT
;
89 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
90 static bool arg_utc
= false;
91 static bool arg_follow
= false;
92 static bool arg_full
= true;
93 static bool arg_all
= false;
94 static PagerFlags arg_pager_flags
= 0;
95 static int arg_lines
= ARG_LINES_DEFAULT
;
96 static bool arg_no_tail
= false;
97 static bool arg_quiet
= false;
98 static bool arg_merge
= false;
99 static bool arg_boot
= false;
100 static sd_id128_t arg_boot_id
= {};
101 static int arg_boot_offset
= 0;
102 static bool arg_dmesg
= false;
103 static bool arg_no_hostname
= false;
104 static const char *arg_cursor
= NULL
;
105 static const char *arg_cursor_file
= NULL
;
106 static const char *arg_after_cursor
= NULL
;
107 static bool arg_show_cursor
= false;
108 static const char *arg_directory
= NULL
;
109 static char **arg_file
= NULL
;
110 static bool arg_file_stdin
= false;
111 static int arg_priorities
= 0xFF;
112 static Set
*arg_facilities
= NULL
;
113 static char *arg_verify_key
= NULL
;
115 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
116 static bool arg_force
= false;
118 static usec_t arg_since
, arg_until
;
119 static bool arg_since_set
= false, arg_until_set
= false;
120 static char **arg_syslog_identifier
= NULL
;
121 static char **arg_system_units
= NULL
;
122 static char **arg_user_units
= NULL
;
123 static const char *arg_field
= NULL
;
124 static bool arg_catalog
= false;
125 static bool arg_reverse
= false;
126 static int arg_journal_type
= 0;
127 static int arg_namespace_flags
= 0;
128 static char *arg_root
= NULL
;
129 static char *arg_image
= NULL
;
130 static const char *arg_machine
= NULL
;
131 static const char *arg_namespace
= NULL
;
132 static uint64_t arg_vacuum_size
= 0;
133 static uint64_t arg_vacuum_n_files
= 0;
134 static usec_t arg_vacuum_time
= 0;
135 static Set
*arg_output_fields
= NULL
;
136 static const char *arg_pattern
= NULL
;
137 static pcre2_code
*arg_compiled_pattern
= NULL
;
138 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
139 ImagePolicy
*arg_image_policy
= NULL
;
141 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
142 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
143 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
144 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
148 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
151 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
162 ACTION_UPDATE_CATALOG
,
165 ACTION_RELINQUISH_VAR
,
169 ACTION_ROTATE_AND_VACUUM
,
171 ACTION_LIST_FIELD_NAMES
,
172 } arg_action
= ACTION_SHOW
;
174 typedef struct BootId
{
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
)
557 if (streq(optarg
, "help")) {
558 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
562 arg_output
= output_mode_from_string(optarg
);
564 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
566 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
569 if (OUTPUT_MODE_IS_JSON(arg_output
))
570 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
572 arg_json_format_flags
= JSON_FORMAT_OFF
;
590 if (streq(optarg
, "all"))
591 arg_lines
= ARG_LINES_ALL
;
593 r
= safe_atoi(optarg
, &arg_lines
);
594 if (r
< 0 || arg_lines
< 0)
595 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
600 /* Hmm, no argument? Maybe the next
601 * word on the command line is
602 * supposed to be the argument? Let's
603 * see if there is one, and is
607 if (streq(argv
[optind
], "all")) {
608 arg_lines
= ARG_LINES_ALL
;
610 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
624 arg_action
= ACTION_NEW_ID128
;
637 arg_boot_id
= SD_ID128_NULL
;
643 arg_boot_id
= SD_ID128_NULL
;
647 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
649 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
653 /* Hmm, no argument? Maybe the next
654 * word on the command line is
655 * supposed to be the argument? Let's
656 * see if there is one and is parsable
657 * as a boot descriptor... */
658 } else if (optind
< argc
) {
659 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
668 arg_action
= ACTION_LIST_BOOTS
;
672 arg_boot
= arg_dmesg
= true;
676 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
680 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
684 arg_machine
= optarg
;
688 if (streq(optarg
, "*")) {
689 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
690 arg_namespace
= NULL
;
691 } else if (startswith(optarg
, "+")) {
692 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
693 arg_namespace
= optarg
+ 1;
694 } else if (isempty(optarg
)) {
695 arg_namespace_flags
= 0;
696 arg_namespace
= NULL
;
698 arg_namespace_flags
= 0;
699 arg_namespace
= optarg
;
705 arg_directory
= optarg
;
709 if (streq(optarg
, "-"))
710 /* An undocumented feature: we can read journal files from STDIN. We don't document
711 * this though, since after all we only support this for mmap-able, seekable files, and
712 * not for example pipes which are probably the primary usecase for reading things from
713 * STDIN. To avoid confusion we hence don't document this feature. */
714 arg_file_stdin
= true;
716 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
718 return log_error_errno(r
, "Failed to add paths: %m");
723 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
729 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
734 case ARG_IMAGE_POLICY
:
735 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
744 case ARG_CURSOR_FILE
:
745 arg_cursor_file
= optarg
;
748 case ARG_AFTER_CURSOR
:
749 arg_after_cursor
= optarg
;
752 case ARG_SHOW_CURSOR
:
753 arg_show_cursor
= true;
757 arg_action
= ACTION_PRINT_HEADER
;
761 arg_action
= ACTION_VERIFY
;
765 arg_action
= ACTION_DISK_USAGE
;
768 case ARG_VACUUM_SIZE
:
769 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
771 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
773 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
776 case ARG_VACUUM_FILES
:
777 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
779 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
781 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
784 case ARG_VACUUM_TIME
:
785 r
= parse_sec(optarg
, &arg_vacuum_time
);
787 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
789 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
798 arg_action
= ACTION_SETUP_KEYS
;
802 r
= free_and_strdup(&arg_verify_key
, optarg
);
805 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
806 * in ps or htop output. */
807 memset(optarg
, 'x', strlen(optarg
));
809 arg_action
= ACTION_VERIFY
;
814 r
= parse_sec(optarg
, &arg_interval
);
815 if (r
< 0 || arg_interval
<= 0)
816 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
817 "Failed to parse sealing key change interval: %s", optarg
);
824 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
825 "Compiled without forward-secure sealing support.");
831 dots
= strstr(optarg
, "..");
833 _cleanup_free_
char *a
= NULL
;
837 a
= strndup(optarg
, dots
- optarg
);
841 from
= log_level_from_string(a
);
842 to
= log_level_from_string(dots
+ 2);
844 if (from
< 0 || to
< 0)
845 return log_error_errno(from
< 0 ? from
: to
,
846 "Failed to parse log level range %s", optarg
);
851 for (i
= from
; i
<= to
; i
++)
852 arg_priorities
|= 1 << i
;
854 for (i
= to
; i
<= from
; i
++)
855 arg_priorities
|= 1 << i
;
861 p
= log_level_from_string(optarg
);
863 return log_error_errno(p
, "Unknown log level %s", optarg
);
867 for (i
= 0; i
<= p
; i
++)
868 arg_priorities
|= 1 << i
;
878 _cleanup_free_
char *fac
= NULL
;
881 r
= extract_first_word(&p
, &fac
, ",", 0);
883 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
887 if (streq(fac
, "help")) {
892 num
= log_facility_unshifted_from_string(fac
);
894 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
896 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
904 arg_pattern
= optarg
;
907 case ARG_CASE_SENSITIVE
:
909 r
= parse_boolean(optarg
);
911 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
912 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
914 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
919 r
= parse_timestamp(optarg
, &arg_since
);
921 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
922 "Failed to parse timestamp: %s", optarg
);
923 arg_since_set
= true;
927 r
= parse_timestamp(optarg
, &arg_until
);
929 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
930 "Failed to parse timestamp: %s", optarg
);
931 arg_until_set
= true;
935 r
= strv_extend(&arg_syslog_identifier
, optarg
);
941 r
= strv_extend(&arg_system_units
, optarg
);
947 r
= strv_extend(&arg_user_units
, optarg
);
953 arg_action
= ACTION_LIST_FIELDS
;
958 arg_action
= ACTION_LIST_FIELD_NAMES
;
961 case ARG_NO_HOSTNAME
:
962 arg_no_hostname
= true;
969 case ARG_LIST_CATALOG
:
970 arg_action
= ACTION_LIST_CATALOG
;
973 case ARG_DUMP_CATALOG
:
974 arg_action
= ACTION_DUMP_CATALOG
;
977 case ARG_UPDATE_CATALOG
:
978 arg_action
= ACTION_UPDATE_CATALOG
;
990 arg_action
= ACTION_FLUSH
;
993 case ARG_SMART_RELINQUISH_VAR
: {
994 int root_mnt_id
, log_mnt_id
;
996 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
997 * if it's on the same mount as the root file system there's no point in
998 * relinquishing access and we can leave journald write to it until the very last
1001 r
= path_get_mnt_id("/", &root_mnt_id
);
1003 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1005 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1007 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1008 else if (root_mnt_id
== log_mnt_id
) {
1009 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1012 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1018 case ARG_RELINQUISH_VAR
:
1019 arg_action
= ACTION_RELINQUISH_VAR
;
1023 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1027 arg_action
= ACTION_SYNC
;
1030 case ARG_OUTPUT_FIELDS
: {
1031 _cleanup_strv_free_
char **v
= NULL
;
1033 v
= strv_split(optarg
, ",");
1037 r
= set_put_strdupv(&arg_output_fields
, v
);
1047 assert_not_reached();
1050 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
1053 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1055 arg_boot_id
= SD_ID128_NULL
;
1056 arg_boot_offset
= 0;
1059 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1060 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1061 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1063 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1064 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1065 "--since= must be before --until=.");
1067 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1068 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1069 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1071 if (arg_follow
&& arg_reverse
)
1072 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1073 "Please specify either --reverse= or --follow=, not both.");
1075 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1076 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1077 "Extraneous arguments starting with '%s'",
1080 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1081 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1082 "Using --boot or --list-boots with --merge is not supported.");
1084 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1085 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1086 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1087 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1088 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1092 arg_system_units
= strv_free(arg_system_units
);
1096 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1100 /* When --grep is used along with --lines, we don't know how many lines we can print.
1101 * So we search backwards and count until enough lines have been printed or we hit the head.
1102 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1103 * if that is specified. */
1104 if (arg_lines
>= 0 && !arg_follow
)
1111 static int add_matches(sd_journal
*j
, char **args
) {
1112 bool have_term
= false;
1116 STRV_FOREACH(i
, args
) {
1119 if (streq(*i
, "+")) {
1122 r
= sd_journal_add_disjunction(j
);
1125 } else if (path_is_absolute(*i
)) {
1126 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1129 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1131 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1133 if (lstat(p
, &st
) < 0)
1134 return log_error_errno(errno
, "Couldn't stat file: %m");
1136 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1137 if (executable_is_script(p
, &interpreter
) > 0) {
1138 _cleanup_free_
char *comm
= NULL
;
1140 r
= path_extract_filename(p
, &comm
);
1142 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1144 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1148 /* Append _EXE only if the interpreter is not a link.
1149 Otherwise, it might be outdated often. */
1150 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1151 t2
= strjoin("_EXE=", interpreter
);
1156 t
= strjoin("_EXE=", p
);
1161 r
= sd_journal_add_match(j
, t
, 0);
1164 r
= sd_journal_add_match(j
, t2
, 0);
1166 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1167 r
= add_matches_for_device(j
, p
);
1171 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1172 "File is neither a device node, nor regular file, nor executable: %s",
1177 r
= sd_journal_add_match(j
, *i
, 0);
1182 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1185 if (!strv_isempty(args
) && !have_term
)
1186 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1187 "\"+\" can only be used between terms");
1192 static int discover_next_boot(
1194 sd_id128_t previous_boot_id
,
1204 /* We expect the journal to be on the last position of a boot
1205 * (in relation to the direction we are going), so that the next
1206 * invocation of sd_journal_next/previous will be from a different
1207 * boot. We then collect any information we desire and then jump
1208 * to the last location of the new boot by using a _BOOT_ID match
1209 * coming from the other journal direction. */
1211 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1212 * we can actually advance to a *different* boot. */
1213 sd_journal_flush_matches(j
);
1217 r
= sd_journal_previous(j
);
1219 r
= sd_journal_next(j
);
1224 return 0; /* End of journal, yay. */
1227 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot
.id
);
1231 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1232 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1233 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1234 * complete than the main entry array, and hence might reference an entry that's not actually the last
1235 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1236 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1239 } while (sd_id128_equal(boot
.id
, previous_boot_id
));
1241 r
= sd_journal_get_realtime_usec(j
, &boot
.first_usec
);
1245 /* Now seek to the last occurrence of this boot ID. */
1246 r
= add_match_boot_id(j
, boot
.id
);
1251 r
= sd_journal_seek_head(j
);
1253 r
= sd_journal_seek_tail(j
);
1258 r
= sd_journal_next(j
);
1260 r
= sd_journal_previous(j
);
1264 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1265 "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. */
1267 r
= sd_journal_get_realtime_usec(j
, &boot
.last_usec
);
1271 sd_journal_flush_matches(j
);
1276 static int find_boot_by_id(sd_journal
*j
) {
1281 sd_journal_flush_matches(j
);
1283 r
= add_match_boot_id(j
, arg_boot_id
);
1287 r
= sd_journal_seek_head(j
); /* seek to oldest */
1291 r
= sd_journal_next(j
); /* read the oldest entry */
1295 /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID.
1296 * After flushing the matches, one more invocation of _previous() will hence place us at the
1297 * following entry, which must then have an older boot ID */
1299 sd_journal_flush_matches(j
);
1303 static int find_boot_by_offset(sd_journal
*j
) {
1304 bool advance_older
, skip_once
;
1307 /* Adjust for the asymmetry that offset 0 is the last (and current) boot, while 1 is considered the
1308 * (chronological) first boot in the journal. */
1309 advance_older
= skip_once
= arg_boot_offset
<= 0;
1312 r
= sd_journal_seek_tail(j
); /* seek to newest */
1314 r
= sd_journal_seek_head(j
); /* seek to oldest */
1318 /* No sd_journal_next()/_previous() here.
1320 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1321 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1324 int offset
= arg_boot_offset
;
1325 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1329 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, &boot
);
1333 previous_boot_id
= boot
.id
;
1336 offset
+= advance_older
? 1 : -1;
1340 arg_boot_id
= boot
.id
;
1346 static int get_boots(sd_journal
*j
, BootId
**ret_boots
, size_t *ret_n_boots
) {
1347 _cleanup_free_ BootId
*boots
= NULL
;
1353 assert(ret_n_boots
);
1355 r
= sd_journal_seek_head(j
); /* seek to oldest */
1359 /* No sd_journal_next()/_previous() here.
1361 * At this point the read pointer is positioned before the oldest entry in the whole journal. The
1362 * next invocation of _next() will hence position us at the oldest entry we have. */
1364 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1368 r
= discover_next_boot(j
, previous_boot_id
, /* advance_older = */ false, &boot
);
1374 previous_boot_id
= boot
.id
;
1376 FOREACH_ARRAY(i
, boots
, n_boots
)
1377 if (sd_id128_equal(i
->id
, boot
.id
))
1378 /* The boot id is already stored, something wrong with the journal files.
1379 * Exiting as otherwise this problem would cause an infinite loop. */
1382 if (!GREEDY_REALLOC(boots
, n_boots
+ 1))
1385 boots
[n_boots
++] = boot
;
1388 *ret_boots
= TAKE_PTR(boots
);
1389 *ret_n_boots
= n_boots
;
1393 static int list_boots(sd_journal
*j
) {
1394 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1395 _cleanup_free_ BootId
*boots
= NULL
;
1401 r
= get_boots(j
, &boots
, &n_boots
);
1403 return log_error_errno(r
, "Failed to determine boots: %m");
1407 table
= table_new("idx", "boot id", "first entry", "last entry");
1412 table_set_width(table
, 0);
1414 r
= table_set_json_field_name(table
, 0, "index");
1416 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1418 (void) table_set_sort(table
, (size_t) 0);
1419 (void) table_set_reverse(table
, 0, arg_reverse
);
1421 FOREACH_ARRAY(i
, boots
, n_boots
) {
1422 r
= table_add_many(table
,
1423 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1424 TABLE_SET_ALIGN_PERCENT
, 100,
1426 TABLE_TIMESTAMP
, i
->first_usec
,
1427 TABLE_TIMESTAMP
, i
->last_usec
);
1429 return table_log_add_error(r
);
1432 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1434 return table_log_print_error(r
);
1439 static int add_boot(sd_journal
*j
) {
1447 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1448 * We can do this only when we logs are coming from the current machine,
1449 * so take the slow path if log location is specified. */
1450 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1451 !arg_directory
&& !arg_file
&& !arg_root
)
1452 return add_match_this_boot(j
, arg_machine
);
1454 if (sd_id128_is_null(arg_boot_id
)) {
1455 r
= find_boot_by_offset(j
);
1457 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1460 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1461 "No journal boot entry found from the specified boot offset (%+i).",
1464 r
= find_boot_by_id(j
);
1466 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1467 SD_ID128_TO_STRING(arg_boot_id
));
1469 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1470 "No journal boot entry found from the specified boot ID (%s).",
1471 SD_ID128_TO_STRING(arg_boot_id
));
1474 r
= add_match_boot_id(j
, arg_boot_id
);
1476 return log_error_errno(r
, "Failed to add match: %m");
1478 r
= sd_journal_add_conjunction(j
);
1480 return log_error_errno(r
, "Failed to add conjunction: %m");
1485 static int add_dmesg(sd_journal
*j
) {
1492 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1493 STRLEN("_TRANSPORT=kernel"));
1495 return log_error_errno(r
, "Failed to add match: %m");
1497 r
= sd_journal_add_conjunction(j
);
1499 return log_error_errno(r
, "Failed to add conjunction: %m");
1504 static int get_possible_units(
1510 _cleanup_set_free_free_ Set
*found
= NULL
;
1513 found
= set_new(&string_hash_ops
);
1517 NULSTR_FOREACH(field
, fields
) {
1521 r
= sd_journal_query_unique(j
, field
);
1525 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1528 _cleanup_free_
char *u
= NULL
;
1530 eq
= memchr(data
, '=', size
);
1532 prefix
= eq
- (char*) data
+ 1;
1536 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1540 STRV_FOREACH(pattern
, patterns
)
1541 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1542 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1544 r
= set_consume(found
, u
);
1546 if (r
< 0 && r
!= -EEXIST
)
1554 *units
= TAKE_PTR(found
);
1559 /* This list is supposed to return the superset of unit names
1560 * possibly matched by rules added with add_matches_for_unit... */
1561 #define SYSTEM_UNITS \
1565 "OBJECT_SYSTEMD_UNIT\0" \
1568 /* ... and add_matches_for_user_unit */
1569 #define USER_UNITS \
1570 "_SYSTEMD_USER_UNIT\0" \
1572 "COREDUMP_USER_UNIT\0" \
1573 "OBJECT_SYSTEMD_USER_UNIT\0" \
1574 "_SYSTEMD_USER_SLICE\0"
1576 static int add_units(sd_journal
*j
) {
1577 _cleanup_strv_free_
char **patterns
= NULL
;
1582 STRV_FOREACH(i
, arg_system_units
) {
1583 _cleanup_free_
char *u
= NULL
;
1585 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1589 if (string_is_glob(u
)) {
1590 r
= strv_push(&patterns
, u
);
1595 r
= add_matches_for_unit(j
, u
);
1598 r
= sd_journal_add_disjunction(j
);
1605 if (!strv_isempty(patterns
)) {
1606 _cleanup_set_free_free_ Set
*units
= NULL
;
1609 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1613 SET_FOREACH(u
, units
) {
1614 r
= add_matches_for_unit(j
, u
);
1617 r
= sd_journal_add_disjunction(j
);
1624 patterns
= strv_free(patterns
);
1626 STRV_FOREACH(i
, arg_user_units
) {
1627 _cleanup_free_
char *u
= NULL
;
1629 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1633 if (string_is_glob(u
)) {
1634 r
= strv_push(&patterns
, u
);
1639 r
= add_matches_for_user_unit(j
, u
, getuid());
1642 r
= sd_journal_add_disjunction(j
);
1649 if (!strv_isempty(patterns
)) {
1650 _cleanup_set_free_free_ Set
*units
= NULL
;
1653 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1657 SET_FOREACH(u
, units
) {
1658 r
= add_matches_for_user_unit(j
, u
, getuid());
1661 r
= sd_journal_add_disjunction(j
);
1668 /* Complain if the user request matches but nothing whatsoever was
1669 * found, since otherwise everything would be matched. */
1670 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1673 r
= sd_journal_add_conjunction(j
);
1680 static int add_priorities(sd_journal
*j
) {
1681 char match
[] = "PRIORITY=0";
1685 if (arg_priorities
== 0xFF)
1688 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1689 if (arg_priorities
& (1 << i
)) {
1690 match
[sizeof(match
)-2] = '0' + i
;
1692 r
= sd_journal_add_match(j
, match
, strlen(match
));
1694 return log_error_errno(r
, "Failed to add match: %m");
1697 r
= sd_journal_add_conjunction(j
);
1699 return log_error_errno(r
, "Failed to add conjunction: %m");
1704 static int add_facilities(sd_journal
*j
) {
1708 SET_FOREACH(p
, arg_facilities
) {
1709 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1711 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1713 r
= sd_journal_add_match(j
, match
, strlen(match
));
1715 return log_error_errno(r
, "Failed to add match: %m");
1721 static int add_syslog_identifier(sd_journal
*j
) {
1726 STRV_FOREACH(i
, arg_syslog_identifier
) {
1727 _cleanup_free_
char *u
= NULL
;
1729 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1732 r
= sd_journal_add_match(j
, u
, 0);
1735 r
= sd_journal_add_disjunction(j
);
1740 r
= sd_journal_add_conjunction(j
);
1748 static int format_journal_url(
1757 _cleanup_free_
char *url
= NULL
;
1758 _cleanup_fclose_
FILE *f
= NULL
;
1759 size_t url_size
= 0;
1763 assert(seed_size
> 0);
1765 f
= open_memstream_unlocked(&url
, &url_size
);
1772 for (size_t i
= 0; i
< seed_size
; i
++) {
1773 if (i
> 0 && i
% 3 == 0)
1775 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1778 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1781 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1783 fprintf(f
, ";hostname=%s", hn
);
1786 r
= fflush_and_check(f
);
1795 *ret_url
= TAKE_PTR(url
);
1800 static int setup_keys(void) {
1802 size_t mpk_size
, seed_size
, state_size
;
1803 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1804 _cleanup_free_
char *p
= NULL
;
1805 uint8_t *mpk
, *seed
, *state
;
1806 _cleanup_close_
int fd
= -EBADF
;
1807 sd_id128_t machine
, boot
;
1812 r
= stat("/var/log/journal", &st
);
1813 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1814 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1816 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1817 log_error("%s is not a directory, must be using persistent logging for FSS.",
1818 "/var/log/journal");
1819 return r
< 0 ? -errno
: -ENOTDIR
;
1822 r
= sd_id128_get_machine(&machine
);
1824 return log_error_errno(r
, "Failed to get machine ID: %m");
1826 r
= sd_id128_get_boot(&boot
);
1828 return log_error_errno(r
, "Failed to get boot ID: %m");
1830 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1831 SD_ID128_FORMAT_VAL(machine
)) < 0)
1836 if (r
< 0 && errno
!= ENOENT
)
1837 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1838 } else if (access(p
, F_OK
) >= 0)
1839 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1840 "Sealing key file %s exists already. Use --force to recreate.", p
);
1842 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1843 SD_ID128_FORMAT_VAL(machine
)) < 0)
1846 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1847 mpk
= alloca_safe(mpk_size
);
1849 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1850 seed
= alloca_safe(seed_size
);
1852 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1853 state
= alloca_safe(state_size
);
1855 log_info("Generating seed...");
1856 r
= crypto_random_bytes(seed
, seed_size
);
1858 return log_error_errno(r
, "Failed to acquire random seed: %m");
1860 log_info("Generating key pair...");
1861 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1863 log_info("Generating sealing key...");
1864 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1866 assert(arg_interval
> 0);
1868 n
= now(CLOCK_REALTIME
);
1872 fd
= mkostemp_safe(k
);
1874 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1876 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1878 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1879 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1881 struct FSSHeader h
= {
1882 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1883 .machine_id
= machine
,
1885 .header_size
= htole64(sizeof(h
)),
1886 .start_usec
= htole64(n
* arg_interval
),
1887 .interval_usec
= htole64(arg_interval
),
1888 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1889 .fsprg_state_size
= htole64(state_size
),
1892 r
= loop_write(fd
, &h
, sizeof(h
), false);
1894 return log_error_errno(r
, "Failed to write header: %m");
1896 r
= loop_write(fd
, state
, state_size
, false);
1898 return log_error_errno(r
, "Failed to write state: %m");
1900 if (rename(k
, p
) < 0)
1901 return log_error_errno(errno
, "Failed to link file: %m");
1905 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1907 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1912 hn
= gethostname_malloc();
1914 hostname_cleanup(hn
);
1917 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1919 "The %ssecret sealing key%s has been written to the following local file.\n"
1920 "This key file is automatically updated when the sealing key is advanced.\n"
1921 "It should not be used on multiple hosts.\n"
1925 "The sealing key is automatically changed every %s.\n"
1927 "Please write down the following %ssecret verification key%s. It should be stored\n"
1928 "in a safe location and should not be saved locally on disk.\n"
1930 strempty(hn
), hn
? "/" : "",
1931 SD_ID128_FORMAT_VAL(machine
),
1932 ansi_highlight(), ansi_normal(),
1934 FORMAT_TIMESPAN(arg_interval
, 0),
1935 ansi_highlight(), ansi_normal(),
1936 ansi_highlight_red());
1943 fprintf(stderr
, "%s", ansi_normal());
1945 _cleanup_free_
char *url
= NULL
;
1946 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1950 (void) print_qrcode(stderr
,
1951 "To transfer the verification key to your phone scan the QR code below",
1958 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1959 "Forward-secure sealing not available.");
1963 static int verify(sd_journal
*j
, bool verbose
) {
1969 log_show_color(true);
1971 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1973 usec_t first
= 0, validated
= 0, last
= 0;
1976 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1977 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1980 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1982 /* If the key was invalid give up right-away. */
1985 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1987 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1988 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1990 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1991 if (validated
> 0) {
1992 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1993 "=> Validated from %s to %s, final %s entries not sealed.",
1994 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1995 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1996 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
1997 } else if (last
> 0)
1998 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1999 "=> No sealing yet, %s of entries not sealed.",
2000 FORMAT_TIMESPAN(last
- first
, 0));
2002 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2003 "=> No sealing yet, no entries in file.");
2011 static int simple_varlink_call(const char *option
, const char *method
) {
2012 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2013 const char *error
, *fn
;
2017 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2019 fn
= arg_namespace
?
2020 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2021 "/run/systemd/journal/io.systemd.journal";
2023 r
= varlink_connect_address(&link
, fn
);
2025 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2027 (void) varlink_set_description(link
, "journal");
2028 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2030 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2032 return log_error_errno(r
, "Failed to execute varlink call: %m");
2034 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2035 "Failed to execute varlink call: %s", error
);
2040 static int flush_to_var(void) {
2041 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2042 return 0; /* Already flushed, no need to contact journald */
2043 if (errno
!= ENOENT
)
2044 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2046 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2049 static int relinquish_var(void) {
2050 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2053 static int rotate(void) {
2054 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2057 static int sync_journal(void) {
2058 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2061 static int wait_for_change(sd_journal
*j
, int poll_fd
) {
2062 struct pollfd pollfds
[] = {
2063 { .fd
= poll_fd
, .events
= POLLIN
},
2064 { .fd
= STDOUT_FILENO
},
2070 assert(poll_fd
>= 0);
2072 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
2073 * i.e. when it is closed. */
2075 r
= sd_journal_get_timeout(j
, &timeout
);
2077 return log_error_errno(r
, "Failed to determine journal waiting time: %m");
2079 r
= ppoll_usec(pollfds
, ELEMENTSOF(pollfds
), timeout
);
2083 return log_error_errno(r
, "Couldn't wait for journal event: %m");
2085 if (pollfds
[1].revents
& (POLLHUP
|POLLERR
)) /* STDOUT has been closed? */
2086 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
),
2087 "Standard output has been closed.");
2089 r
= sd_journal_process(j
);
2091 return log_error_errno(r
, "Failed to process journal events: %m");
2096 static int run(int argc
, char *argv
[]) {
2097 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2098 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2099 bool previous_boot_id_valid
= false, first_line
= true, ellipsized
= false, need_seek
= false, since_seeked
= false;
2100 bool use_cursor
= false, after_cursor
= false;
2101 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2102 sd_id128_t previous_boot_id
= SD_ID128_NULL
, previous_boot_id_output
= SD_ID128_NULL
;
2103 dual_timestamp previous_ts_output
= DUAL_TIMESTAMP_NULL
;
2104 _cleanup_close_
int machine_fd
= -EBADF
;
2105 int n_shown
= 0, r
, poll_fd
= -EBADF
;
2107 setlocale(LC_ALL
, "");
2110 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2111 * split up into many files. */
2112 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2114 r
= parse_argv(argc
, argv
);
2121 r
= mount_image_privately_interactively(
2124 DISSECT_IMAGE_GENERIC_ROOT
|
2125 DISSECT_IMAGE_REQUIRE_ROOT
|
2126 DISSECT_IMAGE_VALIDATE_OS
|
2127 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2128 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2130 /* ret_dir_fd= */ NULL
,
2135 arg_root
= strdup(mounted_dir
);
2140 signal(SIGWINCH
, columns_lines_cache_reset
);
2143 switch (arg_action
) {
2145 case ACTION_NEW_ID128
:
2146 return id128_print_new(ID128_PRINT_PRETTY
);
2148 case ACTION_SETUP_KEYS
:
2149 return setup_keys();
2151 case ACTION_LIST_CATALOG
:
2152 case ACTION_DUMP_CATALOG
:
2153 case ACTION_UPDATE_CATALOG
: {
2154 _cleanup_free_
char *database
= NULL
;
2156 database
= path_join(arg_root
, CATALOG_DATABASE
);
2160 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2161 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2163 return log_error_errno(r
, "Failed to list catalog: %m");
2165 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2167 pager_open(arg_pager_flags
);
2170 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2172 r
= catalog_list(stdout
, database
, oneline
);
2174 return log_error_errno(r
, "Failed to list catalog: %m");
2181 return flush_to_var();
2183 case ACTION_RELINQUISH_VAR
:
2184 return relinquish_var();
2187 return sync_journal();
2193 case ACTION_PRINT_HEADER
:
2195 case ACTION_DISK_USAGE
:
2196 case ACTION_LIST_BOOTS
:
2198 case ACTION_ROTATE_AND_VACUUM
:
2199 case ACTION_LIST_FIELDS
:
2200 case ACTION_LIST_FIELD_NAMES
:
2201 /* These ones require access to the journal files, continue below. */
2205 assert_not_reached();
2209 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2211 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2212 else if (arg_file_stdin
)
2213 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2215 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2216 else if (arg_machine
) {
2217 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2218 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2219 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2223 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2224 * the container, thus we need root privileges to override them. */
2225 return log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2227 r
= sd_bus_open_system(&bus
);
2229 return log_error_errno(r
, "Failed to open system bus: %m");
2231 r
= bus_call_method(bus
, bus_machine_mgr
, "OpenMachineRootDirectory", &error
, &reply
, "s", arg_machine
);
2233 return log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2235 r
= sd_bus_message_read(reply
, "h", &fd
);
2237 return bus_log_parse_error(r
);
2239 machine_fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2241 return log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2243 r
= sd_journal_open_directory_fd(&j
, machine_fd
, SD_JOURNAL_OS_ROOT
);
2245 r
= sd_journal_open_namespace(
2248 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2249 arg_namespace_flags
| arg_journal_type
);
2251 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2253 r
= journal_access_check_and_warn(j
, arg_quiet
,
2254 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2258 switch (arg_action
) {
2260 case ACTION_NEW_ID128
:
2261 case ACTION_SETUP_KEYS
:
2262 case ACTION_LIST_CATALOG
:
2263 case ACTION_DUMP_CATALOG
:
2264 case ACTION_UPDATE_CATALOG
:
2268 assert_not_reached();
2270 case ACTION_PRINT_HEADER
:
2271 journal_print_header(j
);
2275 return verify(j
, !arg_quiet
);
2277 case ACTION_DISK_USAGE
: {
2280 r
= sd_journal_get_usage(j
, &bytes
);
2284 printf("Archived and active journals take up %s in the file system.\n",
2285 FORMAT_BYTES(bytes
));
2290 case ACTION_LIST_BOOTS
:
2291 return list_boots(j
);
2293 case ACTION_ROTATE_AND_VACUUM
:
2301 case ACTION_VACUUM
: {
2305 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2306 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2308 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2317 case ACTION_LIST_FIELD_NAMES
: {
2320 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2321 printf("%s\n", field
);
2327 case ACTION_LIST_FIELDS
:
2331 assert_not_reached();
2334 if (arg_boot_offset
!= 0 &&
2335 sd_journal_has_runtime_files(j
) > 0 &&
2336 sd_journal_has_persistent_files(j
) == 0) {
2337 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2339 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2344 /* add_boot() must be called first!
2345 * It may need to seek the journal to find parent boot IDs. */
2356 return log_error_errno(r
, "Failed to add filter for units: %m");
2358 r
= add_syslog_identifier(j
);
2360 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2362 r
= add_priorities(j
);
2366 r
= add_facilities(j
);
2370 r
= add_matches(j
, argv
+ optind
);
2374 if (DEBUG_LOGGING
) {
2375 _cleanup_free_
char *filter
= NULL
;
2377 filter
= journal_make_match_string(j
);
2381 log_debug("Journal filter: %s", filter
);
2384 if (arg_action
== ACTION_LIST_FIELDS
) {
2390 r
= sd_journal_set_data_threshold(j
, 0);
2392 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2394 r
= sd_journal_query_unique(j
, arg_field
);
2396 return log_error_errno(r
, "Failed to query unique data objects: %m");
2398 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2401 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2404 eq
= memchr(data
, '=', size
);
2406 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2408 printf("%.*s\n", (int) size
, (const char*) data
);
2416 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2418 poll_fd
= sd_journal_get_fd(j
);
2419 if (poll_fd
== -EMFILE
) {
2420 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2422 } else if (poll_fd
== -EMEDIUMTYPE
)
2423 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2424 else if (poll_fd
< 0)
2425 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2428 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2429 _cleanup_free_
char *cursor_from_file
= NULL
;
2430 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2432 if (arg_cursor_file
) {
2433 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2434 if (r
< 0 && r
!= -ENOENT
)
2435 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2438 cursor
= cursor_from_file
;
2439 after_cursor
= true;
2442 after_cursor
= arg_after_cursor
;
2445 r
= sd_journal_seek_cursor(j
, cursor
);
2447 return log_error_errno(r
, "Failed to seek to cursor: %m");
2455 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2457 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2459 if (after_cursor
&& r
< 2) {
2460 /* We couldn't find the next entry after the cursor. */
2467 } else if (arg_until_set
&& (arg_reverse
|| arg_lines
>= 0)) {
2468 /* If both --until and any of --reverse and --lines is specified, things get
2469 * a little tricky. We seek to the place of --until first. If only --reverse or
2470 * --reverse and --lines is specified, we search backwards and let the output
2471 * counter handle --lines for us. If only --lines is used, we just jump backwards
2472 * arg_lines and search afterwards from there. */
2474 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2476 return log_error_errno(r
, "Failed to seek to date: %m");
2479 r
= sd_journal_previous(j
);
2480 else /* arg_lines >= 0 */
2481 r
= sd_journal_previous_skip(j
, arg_lines
);
2483 } else if (arg_reverse
) {
2484 r
= sd_journal_seek_tail(j
);
2486 return log_error_errno(r
, "Failed to seek to tail: %m");
2488 r
= sd_journal_previous(j
);
2490 } else if (arg_lines
>= 0) {
2491 r
= sd_journal_seek_tail(j
);
2493 return log_error_errno(r
, "Failed to seek to tail: %m");
2495 r
= sd_journal_previous_skip(j
, arg_lines
);
2497 } else if (arg_since_set
) {
2498 /* This is placed after arg_reverse and arg_lines. If --since is used without
2499 * both, we seek to the place of --since and search afterwards from there.
2500 * If used with --reverse or --lines, we seek to the tail first and check if
2501 * the entry is within the range of --since later. */
2503 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2505 return log_error_errno(r
, "Failed to seek to date: %m");
2506 since_seeked
= true;
2508 r
= sd_journal_next(j
);
2511 r
= sd_journal_seek_head(j
);
2513 return log_error_errno(r
, "Failed to seek to head: %m");
2515 r
= sd_journal_next(j
);
2518 return log_error_errno(r
, "Failed to iterate through journal: %m");
2523 pager_open(arg_pager_flags
);
2525 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2527 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2529 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2531 return log_error_errno(r
, "Failed to get cutoff: %m");
2534 printf("-- Journal begins at %s. --\n",
2535 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2537 printf("-- Journal begins at %s, ends at %s. --\n",
2538 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2539 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2544 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2546 size_t highlight
[2] = {};
2550 r
= sd_journal_next(j
);
2552 r
= sd_journal_previous(j
);
2554 return log_error_errno(r
, "Failed to iterate through journal: %m");
2559 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2560 /* If --lines= is set, we usually rely on the n_shown to tell us
2561 * when to stop. However, if --since= is set too, we may end up
2562 * having less than --lines= to output. In this case let's also
2563 * check if the entry is in range. */
2567 r
= sd_journal_get_realtime_usec(j
, &usec
);
2569 return log_error_errno(r
, "Failed to determine timestamp: %m");
2570 if (usec
> arg_until
)
2574 if (arg_since_set
&& (arg_reverse
|| !since_seeked
)) {
2577 r
= sd_journal_get_realtime_usec(j
, &usec
);
2579 return log_error_errno(r
, "Failed to determine timestamp: %m");
2581 if (usec
< arg_since
) {
2583 break; /* Reached the earliest entry */
2585 /* arg_lines >= 0 (!since_seeked):
2586 * We jumped arg_lines back and it seems to be too much */
2587 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2589 return log_error_errno(r
, "Failed to seek to date: %m");
2590 since_seeked
= true;
2595 since_seeked
= true; /* We're surely within the range of --since now */
2598 if (!arg_merge
&& !arg_quiet
) {
2601 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2603 if (previous_boot_id_valid
&&
2604 !sd_id128_equal(boot_id
, previous_boot_id
))
2605 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2606 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2608 previous_boot_id
= boot_id
;
2609 previous_boot_id_valid
= true;
2613 if (arg_compiled_pattern
) {
2614 const void *message
;
2617 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2624 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2627 assert_se(message
= startswith(message
, "MESSAGE="));
2629 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2630 len
- strlen("MESSAGE="), highlight
);
2640 arg_all
* OUTPUT_SHOW_ALL
|
2641 arg_full
* OUTPUT_FULL_WIDTH
|
2642 colors_enabled() * OUTPUT_COLOR
|
2643 arg_catalog
* OUTPUT_CATALOG
|
2644 arg_utc
* OUTPUT_UTC
|
2645 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2647 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2648 arg_output_fields
, highlight
, &ellipsized
,
2649 &previous_ts_output
, &previous_boot_id_output
);
2651 if (r
== -EADDRNOTAVAIL
)
2658 /* If journalctl take a long time to process messages, and during that time journal file
2659 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2660 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2661 * in the "following" case. By periodically calling sd_journal_process() during the processing
2662 * loop we shrink the window of time a client instance has open file descriptors for rotated
2663 * (deleted) journal files. */
2664 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2665 r
= sd_journal_process(j
);
2667 return log_error_errno(r
, "Failed to process inotify events: %m");
2672 if (n_shown
== 0 && !arg_quiet
)
2673 printf("-- No entries --\n");
2679 r
= wait_for_change(j
, poll_fd
);
2686 if (arg_show_cursor
|| arg_cursor_file
) {
2687 _cleanup_free_
char *cursor
= NULL
;
2689 r
= sd_journal_get_cursor(j
, &cursor
);
2690 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2691 return log_error_errno(r
, "Failed to get cursor: %m");
2693 if (arg_show_cursor
)
2694 printf("-- cursor: %s\n", cursor
);
2696 if (arg_cursor_file
) {
2697 r
= write_string_file(arg_cursor_file
, cursor
,
2698 WRITE_STRING_FILE_CREATE
|
2699 WRITE_STRING_FILE_ATOMIC
);
2701 return log_error_errno(r
, "Failed to write new cursor to %s: %m",
2707 if (arg_compiled_pattern
&& n_shown
== 0)
2708 /* --grep was used, no error was thrown, but the pattern didn't
2709 * match anything. Let's mimic grep's behavior here and return
2710 * a non-zero exit code, so journalctl --grep can be used
2711 * in scripts and such */
2717 DEFINE_MAIN_FUNCTION(run
);