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"
26 #include "chase-symlinks.h"
27 #include "chattr-util.h"
28 #include "constants.h"
29 #include "dissect-image.h"
32 #include "format-table.h"
33 #include "format-util.h"
36 #include "glob-util.h"
37 #include "hostname-util.h"
38 #include "id128-print.h"
40 #include "journal-def.h"
41 #include "journal-internal.h"
42 #include "journal-util.h"
43 #include "journal-vacuum.h"
44 #include "journal-verify.h"
45 #include "locale-util.h"
47 #include "logs-show.h"
48 #include "main-func.h"
49 #include "memory-util.h"
50 #include "missing_sched.h"
52 #include "mount-util.h"
53 #include "mountpoint-util.h"
54 #include "nulstr-util.h"
56 #include "parse-argument.h"
57 #include "parse-util.h"
58 #include "path-util.h"
59 #include "pcre2-util.h"
60 #include "pretty-print.h"
61 #include "qrcode-util.h"
62 #include "random-util.h"
63 #include "rlimit-util.h"
66 #include "static-destruct.h"
67 #include "stdio-util.h"
68 #include "string-table.h"
70 #include "syslog-util.h"
71 #include "terminal-util.h"
72 #include "tmpfile-util.h"
73 #include "unit-name.h"
74 #include "user-util.h"
77 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
78 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
81 /* Special values for arg_lines */
82 ARG_LINES_DEFAULT
= -2,
86 static OutputMode arg_output
= OUTPUT_SHORT
;
87 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
88 static bool arg_utc
= false;
89 static bool arg_follow
= false;
90 static bool arg_full
= true;
91 static bool arg_all
= false;
92 static PagerFlags arg_pager_flags
= 0;
93 static int arg_lines
= ARG_LINES_DEFAULT
;
94 static bool arg_no_tail
= false;
95 static bool arg_quiet
= false;
96 static bool arg_merge
= false;
97 static bool arg_boot
= false;
98 static sd_id128_t arg_boot_id
= {};
99 static int arg_boot_offset
= 0;
100 static bool arg_dmesg
= false;
101 static bool arg_no_hostname
= false;
102 static const char *arg_cursor
= NULL
;
103 static const char *arg_cursor_file
= NULL
;
104 static const char *arg_after_cursor
= NULL
;
105 static bool arg_show_cursor
= false;
106 static const char *arg_directory
= NULL
;
107 static char **arg_file
= NULL
;
108 static bool arg_file_stdin
= false;
109 static int arg_priorities
= 0xFF;
110 static Set
*arg_facilities
= NULL
;
111 static char *arg_verify_key
= NULL
;
113 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
114 static bool arg_force
= false;
116 static usec_t arg_since
, arg_until
;
117 static bool arg_since_set
= false, arg_until_set
= false;
118 static char **arg_syslog_identifier
= NULL
;
119 static char **arg_system_units
= NULL
;
120 static char **arg_user_units
= NULL
;
121 static const char *arg_field
= NULL
;
122 static bool arg_catalog
= false;
123 static bool arg_reverse
= false;
124 static int arg_journal_type
= 0;
125 static int arg_namespace_flags
= 0;
126 static char *arg_root
= NULL
;
127 static char *arg_image
= NULL
;
128 static const char *arg_machine
= NULL
;
129 static const char *arg_namespace
= NULL
;
130 static uint64_t arg_vacuum_size
= 0;
131 static uint64_t arg_vacuum_n_files
= 0;
132 static usec_t arg_vacuum_time
= 0;
133 static Set
*arg_output_fields
= NULL
;
134 static const char *arg_pattern
= NULL
;
135 static pcre2_code
*arg_compiled_pattern
= NULL
;
136 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
138 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
139 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
140 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
141 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
142 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
143 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
144 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
158 ACTION_UPDATE_CATALOG
,
161 ACTION_RELINQUISH_VAR
,
165 ACTION_ROTATE_AND_VACUUM
,
167 ACTION_LIST_FIELD_NAMES
,
168 } arg_action
= ACTION_SHOW
;
170 typedef struct BootId
{
174 LIST_FIELDS(struct BootId
, boot_list
);
177 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
178 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
186 if (!path_startswith(devpath
, "/dev/"))
187 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
188 "Devpath does not start with /dev/");
190 if (stat(devpath
, &st
) < 0)
191 return log_error_errno(errno
, "Couldn't stat file: %m");
193 r
= sd_device_new_from_stat_rdev(&device
, &st
);
195 return log_error_errno(r
, "Failed to get device from devnum %u:%u: %m", major(st
.st_rdev
), minor(st
.st_rdev
));
197 for (d
= device
; d
; ) {
198 _cleanup_free_
char *match
= NULL
;
199 const char *subsys
, *sysname
, *devnode
;
202 r
= sd_device_get_subsystem(d
, &subsys
);
206 r
= sd_device_get_sysname(d
, &sysname
);
210 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
214 r
= sd_journal_add_match(j
, match
, 0);
216 return log_error_errno(r
, "Failed to add match: %m");
218 if (sd_device_get_devname(d
, &devnode
) >= 0) {
219 _cleanup_free_
char *match1
= NULL
;
221 r
= stat(devnode
, &st
);
223 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
225 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st
.st_mode
) ? 'b' : 'c', major(st
.st_rdev
), minor(st
.st_rdev
));
229 r
= sd_journal_add_match(j
, match1
, 0);
231 return log_error_errno(r
, "Failed to add match: %m");
235 if (sd_device_get_parent(d
, &parent
) < 0)
241 r
= add_match_this_boot(j
, arg_machine
);
243 return log_error_errno(r
, "Failed to add match for the current boot: %m");
248 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
251 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
253 return format_timestamp(buf
, l
, t
);
256 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
257 sd_id128_t id
= SD_ID128_NULL
;
260 if (streq(x
, "all")) {
261 *boot_id
= SD_ID128_NULL
;
264 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
267 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
268 r
= sd_id128_from_string(t
, &id
);
270 x
+= SD_ID128_STRING_MAX
- 1;
272 if (!IN_SET(*x
, 0, '-', '+'))
276 r
= safe_atoi(x
, &off
);
281 r
= safe_atoi(x
, &off
);
295 static int help_facilities(void) {
297 puts("Available facilities:");
299 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
300 _cleanup_free_
char *t
= NULL
;
302 if (log_facility_unshifted_to_string_alloc(i
, &t
))
310 static int help(void) {
311 _cleanup_free_
char *link
= NULL
;
314 pager_open(arg_pager_flags
);
316 r
= terminal_urlify_man("journalctl", "1", &link
);
320 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
321 "%5$sQuery the journal.%6$s\n\n"
322 "%3$sSource Options:%4$s\n"
323 " --system Show the system journal\n"
324 " --user Show the user journal for the current user\n"
325 " -M --machine=CONTAINER Operate on local container\n"
326 " -m --merge Show entries from all available journals\n"
327 " -D --directory=PATH Show journal files from directory\n"
328 " --file=PATH Show journal file\n"
329 " --root=ROOT Operate on files below a root directory\n"
330 " --image=IMAGE Operate on files in filesystem image\n"
331 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
332 "\n%3$sFiltering Options:%4$s\n"
333 " -S --since=DATE Show entries not older than the specified date\n"
334 " -U --until=DATE Show entries not newer than the specified date\n"
335 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
336 " --after-cursor=CURSOR Show entries after the specified cursor\n"
337 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
338 " -b --boot[=ID] Show current boot or the specified boot\n"
339 " -u --unit=UNIT Show logs from the specified unit\n"
340 " --user-unit=UNIT Show logs from the specified user unit\n"
341 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
342 " -p --priority=RANGE Show entries with the specified priority\n"
343 " --facility=FACILITY... Show entries with the specified facilities\n"
344 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
345 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
346 " -k --dmesg Show kernel message log from the current boot\n"
347 "\n%3$sOutput Control Options:%4$s\n"
348 " -o --output=STRING Change journal output mode (short, short-precise,\n"
349 " short-iso, short-iso-precise, short-full,\n"
350 " short-monotonic, short-unix, verbose, export,\n"
351 " json, json-pretty, json-sse, json-seq, cat,\n"
353 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
354 " -n --lines[=INTEGER] Number of journal entries to show\n"
355 " -r --reverse Show the newest entries first\n"
356 " --show-cursor Print the cursor after all the entries\n"
357 " --utc Express time in Coordinated Universal Time (UTC)\n"
358 " -x --catalog Add message explanations where available\n"
359 " --no-hostname Suppress output of hostname field\n"
360 " --no-full Ellipsize fields\n"
361 " -a --all Show all fields, including long and unprintable\n"
362 " -f --follow Follow the journal\n"
363 " --no-tail Show all lines, even in follow mode\n"
364 " -q --quiet Do not show info messages and privilege warning\n"
365 "\n%3$sPager Control Options:%4$s\n"
366 " --no-pager Do not pipe output into a pager\n"
367 " -e --pager-end Immediately jump to the end in the pager\n"
368 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
369 " --interval=TIME Time interval for changing the FSS sealing key\n"
370 " --verify-key=KEY Specify FSS verification key\n"
371 " --force Override of the FSS key pair with --setup-keys\n"
372 "\n%3$sCommands:%4$s\n"
373 " -h --help Show this help text\n"
374 " --version Show package version\n"
375 " -N --fields List all field names currently used\n"
376 " -F --field=FIELD List all values that a specified field takes\n"
377 " --list-boots Show terse information about recorded boots\n"
378 " --disk-usage Show total disk usage of all journal files\n"
379 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
380 " --vacuum-files=INT Leave only the specified number of journal files\n"
381 " --vacuum-time=TIME Remove journal files older than specified time\n"
382 " --verify Verify journal file consistency\n"
383 " --sync Synchronize unwritten journal messages to disk\n"
384 " --relinquish-var Stop logging to disk, log to temporary file system\n"
385 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
386 " --flush Flush all journal data from /run into /var\n"
387 " --rotate Request immediate rotation of the journal files\n"
388 " --header Show journal header information\n"
389 " --list-catalog Show all message IDs in the catalog\n"
390 " --dump-catalog Show entries in the message catalog\n"
391 " --update-catalog Update the message catalog database\n"
392 " --setup-keys Generate a new FSS key pair\n"
393 "\nSee the %2$s for details.\n",
394 program_invocation_short_name
,
404 static int parse_argv(int argc
, char *argv
[]) {
439 ARG_SMART_RELINQUISH_VAR
,
449 static const struct option options
[] = {
450 { "help", no_argument
, NULL
, 'h' },
451 { "version" , no_argument
, NULL
, ARG_VERSION
},
452 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
453 { "pager-end", no_argument
, NULL
, 'e' },
454 { "follow", no_argument
, NULL
, 'f' },
455 { "force", no_argument
, NULL
, ARG_FORCE
},
456 { "output", required_argument
, NULL
, 'o' },
457 { "all", no_argument
, NULL
, 'a' },
458 { "full", no_argument
, NULL
, 'l' },
459 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
460 { "lines", optional_argument
, NULL
, 'n' },
461 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
462 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
463 { "quiet", no_argument
, NULL
, 'q' },
464 { "merge", no_argument
, NULL
, 'm' },
465 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
466 { "boot", optional_argument
, NULL
, 'b' },
467 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
468 { "dmesg", no_argument
, NULL
, 'k' },
469 { "system", no_argument
, NULL
, ARG_SYSTEM
},
470 { "user", no_argument
, NULL
, ARG_USER
},
471 { "directory", required_argument
, NULL
, 'D' },
472 { "file", required_argument
, NULL
, ARG_FILE
},
473 { "root", required_argument
, NULL
, ARG_ROOT
},
474 { "image", required_argument
, NULL
, ARG_IMAGE
},
475 { "header", no_argument
, NULL
, ARG_HEADER
},
476 { "identifier", required_argument
, NULL
, 't' },
477 { "priority", required_argument
, NULL
, 'p' },
478 { "facility", required_argument
, NULL
, ARG_FACILITY
},
479 { "grep", required_argument
, NULL
, 'g' },
480 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
481 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
482 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
483 { "verify", no_argument
, NULL
, ARG_VERIFY
},
484 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
485 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
486 { "cursor", required_argument
, NULL
, 'c' },
487 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
488 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
489 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
490 { "since", required_argument
, NULL
, 'S' },
491 { "until", required_argument
, NULL
, 'U' },
492 { "unit", required_argument
, NULL
, 'u' },
493 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
494 { "field", required_argument
, NULL
, 'F' },
495 { "fields", no_argument
, NULL
, 'N' },
496 { "catalog", no_argument
, NULL
, 'x' },
497 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
498 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
499 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
500 { "reverse", no_argument
, NULL
, 'r' },
501 { "machine", required_argument
, NULL
, 'M' },
502 { "utc", no_argument
, NULL
, ARG_UTC
},
503 { "flush", no_argument
, NULL
, ARG_FLUSH
},
504 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
505 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
506 { "sync", no_argument
, NULL
, ARG_SYNC
},
507 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
508 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
509 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
510 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
511 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
512 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
513 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
522 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
533 arg_pager_flags
|= PAGER_DISABLE
;
537 arg_pager_flags
|= PAGER_JUMP_TO_END
;
539 if (arg_lines
== ARG_LINES_DEFAULT
)
550 arg_boot_id
= SD_ID128_NULL
;
556 if (streq(optarg
, "help")) {
557 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
561 arg_output
= output_mode_from_string(optarg
);
563 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
565 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
568 if (OUTPUT_MODE_IS_JSON(arg_output
))
569 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
571 arg_json_format_flags
= JSON_FORMAT_OFF
;
589 if (streq(optarg
, "all"))
590 arg_lines
= ARG_LINES_ALL
;
592 r
= safe_atoi(optarg
, &arg_lines
);
593 if (r
< 0 || arg_lines
< 0)
594 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
599 /* Hmm, no argument? Maybe the next
600 * word on the command line is
601 * supposed to be the argument? Let's
602 * see if there is one, and is
606 if (streq(argv
[optind
], "all")) {
607 arg_lines
= ARG_LINES_ALL
;
609 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
623 arg_action
= ACTION_NEW_ID128
;
636 arg_boot_id
= SD_ID128_NULL
;
642 arg_boot_id
= SD_ID128_NULL
;
646 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
648 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
652 /* Hmm, no argument? Maybe the next
653 * word on the command line is
654 * supposed to be the argument? Let's
655 * see if there is one and is parsable
656 * as a boot descriptor... */
657 } else if (optind
< argc
) {
658 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
667 arg_action
= ACTION_LIST_BOOTS
;
671 arg_boot
= arg_dmesg
= true;
675 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
679 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
683 arg_machine
= optarg
;
687 if (streq(optarg
, "*")) {
688 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
689 arg_namespace
= NULL
;
690 } else if (startswith(optarg
, "+")) {
691 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
692 arg_namespace
= optarg
+ 1;
693 } else if (isempty(optarg
)) {
694 arg_namespace_flags
= 0;
695 arg_namespace
= NULL
;
697 arg_namespace_flags
= 0;
698 arg_namespace
= optarg
;
704 arg_directory
= optarg
;
708 if (streq(optarg
, "-"))
709 /* An undocumented feature: we can read journal files from STDIN. We don't document
710 * this though, since after all we only support this for mmap-able, seekable files, and
711 * not for example pipes which are probably the primary usecase for reading things from
712 * STDIN. To avoid confusion we hence don't document this feature. */
713 arg_file_stdin
= true;
715 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
717 return log_error_errno(r
, "Failed to add paths: %m");
722 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
728 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
737 case ARG_CURSOR_FILE
:
738 arg_cursor_file
= optarg
;
741 case ARG_AFTER_CURSOR
:
742 arg_after_cursor
= optarg
;
745 case ARG_SHOW_CURSOR
:
746 arg_show_cursor
= true;
750 arg_action
= ACTION_PRINT_HEADER
;
754 arg_action
= ACTION_VERIFY
;
758 arg_action
= ACTION_DISK_USAGE
;
761 case ARG_VACUUM_SIZE
:
762 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
764 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
766 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
769 case ARG_VACUUM_FILES
:
770 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
772 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
774 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
777 case ARG_VACUUM_TIME
:
778 r
= parse_sec(optarg
, &arg_vacuum_time
);
780 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
782 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
791 arg_action
= ACTION_SETUP_KEYS
;
795 r
= free_and_strdup(&arg_verify_key
, optarg
);
798 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
799 * in ps or htop output. */
800 memset(optarg
, 'x', strlen(optarg
));
802 arg_action
= ACTION_VERIFY
;
807 r
= parse_sec(optarg
, &arg_interval
);
808 if (r
< 0 || arg_interval
<= 0)
809 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
810 "Failed to parse sealing key change interval: %s", optarg
);
817 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
818 "Compiled without forward-secure sealing support.");
824 dots
= strstr(optarg
, "..");
826 _cleanup_free_
char *a
= NULL
;
830 a
= strndup(optarg
, dots
- optarg
);
834 from
= log_level_from_string(a
);
835 to
= log_level_from_string(dots
+ 2);
837 if (from
< 0 || to
< 0)
838 return log_error_errno(from
< 0 ? from
: to
,
839 "Failed to parse log level range %s", optarg
);
844 for (i
= from
; i
<= to
; i
++)
845 arg_priorities
|= 1 << i
;
847 for (i
= to
; i
<= from
; i
++)
848 arg_priorities
|= 1 << i
;
854 p
= log_level_from_string(optarg
);
856 return log_error_errno(p
, "Unknown log level %s", optarg
);
860 for (i
= 0; i
<= p
; i
++)
861 arg_priorities
|= 1 << i
;
871 _cleanup_free_
char *fac
= NULL
;
874 r
= extract_first_word(&p
, &fac
, ",", 0);
876 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
880 if (streq(fac
, "help")) {
885 num
= log_facility_unshifted_from_string(fac
);
887 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
889 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
897 arg_pattern
= optarg
;
900 case ARG_CASE_SENSITIVE
:
902 r
= parse_boolean(optarg
);
904 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
905 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
907 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
912 r
= parse_timestamp(optarg
, &arg_since
);
914 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
915 "Failed to parse timestamp: %s", optarg
);
916 arg_since_set
= true;
920 r
= parse_timestamp(optarg
, &arg_until
);
922 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
923 "Failed to parse timestamp: %s", optarg
);
924 arg_until_set
= true;
928 r
= strv_extend(&arg_syslog_identifier
, optarg
);
934 r
= strv_extend(&arg_system_units
, optarg
);
940 r
= strv_extend(&arg_user_units
, optarg
);
946 arg_action
= ACTION_LIST_FIELDS
;
951 arg_action
= ACTION_LIST_FIELD_NAMES
;
954 case ARG_NO_HOSTNAME
:
955 arg_no_hostname
= true;
962 case ARG_LIST_CATALOG
:
963 arg_action
= ACTION_LIST_CATALOG
;
966 case ARG_DUMP_CATALOG
:
967 arg_action
= ACTION_DUMP_CATALOG
;
970 case ARG_UPDATE_CATALOG
:
971 arg_action
= ACTION_UPDATE_CATALOG
;
983 arg_action
= ACTION_FLUSH
;
986 case ARG_SMART_RELINQUISH_VAR
: {
987 int root_mnt_id
, log_mnt_id
;
989 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
990 * if it's on the same mount as the root file system there's no point in
991 * relinquishing access and we can leave journald write to it until the very last
994 r
= path_get_mnt_id("/", &root_mnt_id
);
996 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
998 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1000 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1001 else if (root_mnt_id
== log_mnt_id
) {
1002 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1005 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1011 case ARG_RELINQUISH_VAR
:
1012 arg_action
= ACTION_RELINQUISH_VAR
;
1016 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1020 arg_action
= ACTION_SYNC
;
1023 case ARG_OUTPUT_FIELDS
: {
1024 _cleanup_strv_free_
char **v
= NULL
;
1026 v
= strv_split(optarg
, ",");
1030 r
= set_put_strdupv(&arg_output_fields
, v
);
1041 assert_not_reached();
1044 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
1047 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1048 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1049 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1051 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1052 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1053 "--since= must be before --until=.");
1055 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1056 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1057 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1059 if (arg_follow
&& arg_reverse
)
1060 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1061 "Please specify either --reverse= or --follow=, not both.");
1063 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1064 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1065 "Extraneous arguments starting with '%s'",
1068 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1069 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1070 "Using --boot or --list-boots with --merge is not supported.");
1072 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1073 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1074 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1075 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1076 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1080 arg_system_units
= strv_free(arg_system_units
);
1084 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1092 static int add_matches(sd_journal
*j
, char **args
) {
1093 bool have_term
= false;
1097 STRV_FOREACH(i
, args
) {
1100 if (streq(*i
, "+")) {
1103 r
= sd_journal_add_disjunction(j
);
1106 } else if (path_is_absolute(*i
)) {
1107 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1110 r
= chase_symlinks(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1112 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1114 if (lstat(p
, &st
) < 0)
1115 return log_error_errno(errno
, "Couldn't stat file: %m");
1117 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1118 if (executable_is_script(p
, &interpreter
) > 0) {
1119 _cleanup_free_
char *comm
= NULL
;
1121 r
= path_extract_filename(p
, &comm
);
1123 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1125 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1129 /* Append _EXE only if the interpreter is not a link.
1130 Otherwise, it might be outdated often. */
1131 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1132 t2
= strjoin("_EXE=", interpreter
);
1137 t
= strjoin("_EXE=", p
);
1142 r
= sd_journal_add_match(j
, t
, 0);
1145 r
= sd_journal_add_match(j
, t2
, 0);
1147 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1148 r
= add_matches_for_device(j
, p
);
1152 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1153 "File is neither a device node, nor regular file, nor executable: %s",
1158 r
= sd_journal_add_match(j
, *i
, 0);
1163 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1166 if (!strv_isempty(args
) && !have_term
)
1167 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1168 "\"+\" can only be used between terms");
1173 static void boot_id_free_all(BootId
*l
) {
1177 LIST_REMOVE(boot_list
, l
, i
);
1182 static int discover_next_boot(sd_journal
*j
,
1183 sd_id128_t previous_boot_id
,
1187 _cleanup_free_ BootId
*next_boot
= NULL
;
1188 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1195 /* We expect the journal to be on the last position of a boot
1196 * (in relation to the direction we are going), so that the next
1197 * invocation of sd_journal_next/previous will be from a different
1198 * boot. We then collect any information we desire and then jump
1199 * to the last location of the new boot by using a _BOOT_ID match
1200 * coming from the other journal direction. */
1202 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1203 * we can actually advance to a *different* boot. */
1204 sd_journal_flush_matches(j
);
1208 r
= sd_journal_previous(j
);
1210 r
= sd_journal_next(j
);
1214 return 0; /* End of journal, yay. */
1216 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1220 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1221 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1222 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1223 * complete than the main entry array, and hence might reference an entry that's not actually the last
1224 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1225 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1228 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1230 next_boot
= new0(BootId
, 1);
1234 next_boot
->id
= boot_id
;
1236 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1240 /* Now seek to the last occurrence of this boot ID. */
1241 sd_id128_to_string(next_boot
->id
, match
+ STRLEN("_BOOT_ID="));
1242 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1247 r
= sd_journal_seek_head(j
);
1249 r
= sd_journal_seek_tail(j
);
1254 r
= sd_journal_next(j
);
1256 r
= sd_journal_previous(j
);
1260 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1261 "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. */
1263 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1267 *ret
= TAKE_PTR(next_boot
);
1272 static int get_boots(
1275 sd_id128_t
*boot_id
,
1280 BootId
*head
= NULL
, *tail
= NULL
;
1281 const bool advance_older
= boot_id
&& offset
<= 0;
1282 sd_id128_t previous_boot_id
;
1286 /* Adjust for the asymmetry that offset 0 is
1287 * the last (and current) boot, while 1 is considered the
1288 * (chronological) first boot in the journal. */
1289 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1291 /* Advance to the earliest/latest occurrence of our reference
1292 * boot ID (taking our lookup direction into account), so that
1293 * discover_next_boot() can do its job.
1294 * If no reference is given, the journal head/tail will do,
1295 * they're "virtual" boots after all. */
1296 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1297 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1299 sd_journal_flush_matches(j
);
1301 sd_id128_to_string(*boot_id
, match
+ STRLEN("_BOOT_ID="));
1302 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1307 r
= sd_journal_seek_head(j
); /* seek to oldest */
1309 r
= sd_journal_seek_tail(j
); /* seek to newest */
1314 r
= sd_journal_next(j
); /* read the oldest entry */
1316 r
= sd_journal_previous(j
); /* read the most recently added entry */
1321 else if (offset
== 0) {
1326 /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot
1327 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1328 * the following entry, which must then have an older/newer boot ID */
1332 r
= sd_journal_seek_tail(j
); /* seek to newest */
1334 r
= sd_journal_seek_head(j
); /* seek to oldest */
1338 /* No sd_journal_next()/_previous() here.
1340 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1341 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1345 previous_boot_id
= SD_ID128_NULL
;
1347 _cleanup_free_ BootId
*current
= NULL
;
1349 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1351 boot_id_free_all(head
);
1358 previous_boot_id
= current
->id
;
1362 offset
+= advance_older
? 1 : -1;
1367 *boot_id
= current
->id
;
1371 LIST_FOREACH(boot_list
, id
, head
) {
1372 if (sd_id128_equal(id
->id
, current
->id
)) {
1373 /* boot id already stored, something wrong with the journal files */
1374 /* exiting as otherwise this problem would cause forever loop */
1378 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1379 tail
= TAKE_PTR(current
);
1388 sd_journal_flush_matches(j
);
1393 static int list_boots(sd_journal
*j
) {
1394 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1400 count
= get_boots(j
, &all_ids
, NULL
, 0);
1402 return log_error_errno(count
, "Failed to determine boots: %m");
1406 table
= table_new("idx", "boot id", "first entry", "last entry");
1411 table_set_width(table
, 0);
1413 r
= table_set_json_field_name(table
, 0, "index");
1415 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1417 (void) table_set_sort(table
, (size_t) 0);
1418 (void) table_set_reverse(table
, 0, arg_reverse
);
1421 LIST_FOREACH(boot_list
, id
, all_ids
) {
1422 r
= table_add_many(table
,
1423 TABLE_INT
, i
- count
+ 1,
1424 TABLE_SET_ALIGN_PERCENT
, 100,
1425 TABLE_ID128
, id
->id
,
1426 TABLE_TIMESTAMP
, id
->first
,
1427 TABLE_TIMESTAMP
, id
->last
);
1429 return table_log_add_error(r
);
1433 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1435 return table_log_print_error(r
);
1437 boot_id_free_all(all_ids
);
1442 static int add_boot(sd_journal
*j
) {
1443 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1452 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1453 * We can do this only when we logs are coming from the current machine,
1454 * so take the slow path if log location is specified. */
1455 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1456 !arg_directory
&& !arg_file
&& !arg_root
)
1457 return add_match_this_boot(j
, arg_machine
);
1459 boot_id
= arg_boot_id
;
1460 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1463 const char *reason
= (r
== 0) ? "No such boot ID in journal" : STRERROR(r
);
1465 if (sd_id128_is_null(arg_boot_id
))
1466 log_error("Data from the specified boot (%+i) is not available: %s",
1467 arg_boot_offset
, reason
);
1469 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1470 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1472 return r
== 0 ? -ENODATA
: r
;
1475 sd_id128_to_string(boot_id
, match
+ STRLEN("_BOOT_ID="));
1477 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1479 return log_error_errno(r
, "Failed to add match: %m");
1481 r
= sd_journal_add_conjunction(j
);
1483 return log_error_errno(r
, "Failed to add conjunction: %m");
1488 static int add_dmesg(sd_journal
*j
) {
1495 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1496 STRLEN("_TRANSPORT=kernel"));
1498 return log_error_errno(r
, "Failed to add match: %m");
1500 r
= sd_journal_add_conjunction(j
);
1502 return log_error_errno(r
, "Failed to add conjunction: %m");
1507 static int get_possible_units(
1513 _cleanup_set_free_free_ Set
*found
= NULL
;
1516 found
= set_new(&string_hash_ops
);
1520 NULSTR_FOREACH(field
, fields
) {
1524 r
= sd_journal_query_unique(j
, field
);
1528 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1531 _cleanup_free_
char *u
= NULL
;
1533 eq
= memchr(data
, '=', size
);
1535 prefix
= eq
- (char*) data
+ 1;
1539 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1543 STRV_FOREACH(pattern
, patterns
)
1544 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1545 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1547 r
= set_consume(found
, u
);
1549 if (r
< 0 && r
!= -EEXIST
)
1557 *units
= TAKE_PTR(found
);
1562 /* This list is supposed to return the superset of unit names
1563 * possibly matched by rules added with add_matches_for_unit... */
1564 #define SYSTEM_UNITS \
1568 "OBJECT_SYSTEMD_UNIT\0" \
1571 /* ... and add_matches_for_user_unit */
1572 #define USER_UNITS \
1573 "_SYSTEMD_USER_UNIT\0" \
1575 "COREDUMP_USER_UNIT\0" \
1576 "OBJECT_SYSTEMD_USER_UNIT\0" \
1577 "_SYSTEMD_USER_SLICE\0"
1579 static int add_units(sd_journal
*j
) {
1580 _cleanup_strv_free_
char **patterns
= NULL
;
1585 STRV_FOREACH(i
, arg_system_units
) {
1586 _cleanup_free_
char *u
= NULL
;
1588 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1592 if (string_is_glob(u
)) {
1593 r
= strv_push(&patterns
, u
);
1598 r
= add_matches_for_unit(j
, u
);
1601 r
= sd_journal_add_disjunction(j
);
1608 if (!strv_isempty(patterns
)) {
1609 _cleanup_set_free_free_ Set
*units
= NULL
;
1612 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1616 SET_FOREACH(u
, units
) {
1617 r
= add_matches_for_unit(j
, u
);
1620 r
= sd_journal_add_disjunction(j
);
1627 patterns
= strv_free(patterns
);
1629 STRV_FOREACH(i
, arg_user_units
) {
1630 _cleanup_free_
char *u
= NULL
;
1632 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1636 if (string_is_glob(u
)) {
1637 r
= strv_push(&patterns
, u
);
1642 r
= add_matches_for_user_unit(j
, u
, getuid());
1645 r
= sd_journal_add_disjunction(j
);
1652 if (!strv_isempty(patterns
)) {
1653 _cleanup_set_free_free_ Set
*units
= NULL
;
1656 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1660 SET_FOREACH(u
, units
) {
1661 r
= add_matches_for_user_unit(j
, u
, getuid());
1664 r
= sd_journal_add_disjunction(j
);
1671 /* Complain if the user request matches but nothing whatsoever was
1672 * found, since otherwise everything would be matched. */
1673 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1676 r
= sd_journal_add_conjunction(j
);
1683 static int add_priorities(sd_journal
*j
) {
1684 char match
[] = "PRIORITY=0";
1688 if (arg_priorities
== 0xFF)
1691 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1692 if (arg_priorities
& (1 << i
)) {
1693 match
[sizeof(match
)-2] = '0' + i
;
1695 r
= sd_journal_add_match(j
, match
, strlen(match
));
1697 return log_error_errno(r
, "Failed to add match: %m");
1700 r
= sd_journal_add_conjunction(j
);
1702 return log_error_errno(r
, "Failed to add conjunction: %m");
1707 static int add_facilities(sd_journal
*j
) {
1711 SET_FOREACH(p
, arg_facilities
) {
1712 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1714 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1716 r
= sd_journal_add_match(j
, match
, strlen(match
));
1718 return log_error_errno(r
, "Failed to add match: %m");
1724 static int add_syslog_identifier(sd_journal
*j
) {
1729 STRV_FOREACH(i
, arg_syslog_identifier
) {
1730 _cleanup_free_
char *u
= NULL
;
1732 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1735 r
= sd_journal_add_match(j
, u
, 0);
1738 r
= sd_journal_add_disjunction(j
);
1743 r
= sd_journal_add_conjunction(j
);
1751 static int format_journal_url(
1760 _cleanup_free_
char *url
= NULL
;
1761 _cleanup_fclose_
FILE *f
= NULL
;
1762 size_t url_size
= 0;
1766 assert(seed_size
> 0);
1768 f
= open_memstream_unlocked(&url
, &url_size
);
1775 for (size_t i
= 0; i
< seed_size
; i
++) {
1776 if (i
> 0 && i
% 3 == 0)
1778 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1781 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1784 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1786 fprintf(f
, ";hostname=%s", hn
);
1789 r
= fflush_and_check(f
);
1794 *ret_url
= TAKE_PTR(url
);
1799 static int setup_keys(void) {
1801 size_t mpk_size
, seed_size
, state_size
;
1802 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1803 _cleanup_free_
char *p
= NULL
;
1804 uint8_t *mpk
, *seed
, *state
;
1805 _cleanup_close_
int fd
= -EBADF
;
1806 sd_id128_t machine
, boot
;
1811 r
= stat("/var/log/journal", &st
);
1812 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1813 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1815 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1816 log_error("%s is not a directory, must be using persistent logging for FSS.",
1817 "/var/log/journal");
1818 return r
< 0 ? -errno
: -ENOTDIR
;
1821 r
= sd_id128_get_machine(&machine
);
1823 return log_error_errno(r
, "Failed to get machine ID: %m");
1825 r
= sd_id128_get_boot(&boot
);
1827 return log_error_errno(r
, "Failed to get boot ID: %m");
1829 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1830 SD_ID128_FORMAT_VAL(machine
)) < 0)
1835 if (r
< 0 && errno
!= ENOENT
)
1836 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1837 } else if (access(p
, F_OK
) >= 0)
1838 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1839 "Sealing key file %s exists already. Use --force to recreate.", p
);
1841 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1842 SD_ID128_FORMAT_VAL(machine
)) < 0)
1845 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1846 mpk
= alloca_safe(mpk_size
);
1848 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1849 seed
= alloca_safe(seed_size
);
1851 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1852 state
= alloca_safe(state_size
);
1854 log_info("Generating seed...");
1855 r
= crypto_random_bytes(seed
, seed_size
);
1857 return log_error_errno(r
, "Failed to acquire random seed: %m");
1859 log_info("Generating key pair...");
1860 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1862 log_info("Generating sealing key...");
1863 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1865 assert(arg_interval
> 0);
1867 n
= now(CLOCK_REALTIME
);
1871 fd
= mkostemp_safe(k
);
1873 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1875 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1877 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1878 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1880 struct FSSHeader h
= {
1881 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1882 .machine_id
= machine
,
1884 .header_size
= htole64(sizeof(h
)),
1885 .start_usec
= htole64(n
* arg_interval
),
1886 .interval_usec
= htole64(arg_interval
),
1887 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1888 .fsprg_state_size
= htole64(state_size
),
1891 r
= loop_write(fd
, &h
, sizeof(h
), false);
1893 return log_error_errno(r
, "Failed to write header: %m");
1895 r
= loop_write(fd
, state
, state_size
, false);
1897 return log_error_errno(r
, "Failed to write state: %m");
1899 if (rename(k
, p
) < 0)
1900 return log_error_errno(errno
, "Failed to link file: %m");
1904 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1906 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1911 hn
= gethostname_malloc();
1913 hostname_cleanup(hn
);
1916 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1918 "The %ssecret sealing key%s has been written to the following local file.\n"
1919 "This key file is automatically updated when the sealing key is advanced.\n"
1920 "It should not be used on multiple hosts.\n"
1924 "The sealing key is automatically changed every %s.\n"
1926 "Please write down the following %ssecret verification key%s. It should be stored\n"
1927 "in a safe location and should not be saved locally on disk.\n"
1929 strempty(hn
), hn
? "/" : "",
1930 SD_ID128_FORMAT_VAL(machine
),
1931 ansi_highlight(), ansi_normal(),
1933 FORMAT_TIMESPAN(arg_interval
, 0),
1934 ansi_highlight(), ansi_normal(),
1935 ansi_highlight_red());
1942 fprintf(stderr
, "%s", ansi_normal());
1944 _cleanup_free_
char *url
= NULL
;
1945 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1949 (void) print_qrcode(stderr
,
1950 "To transfer the verification key to your phone scan the QR code below",
1957 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1958 "Forward-secure sealing not available.");
1962 static int verify(sd_journal
*j
, bool verbose
) {
1968 log_show_color(true);
1970 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1972 usec_t first
= 0, validated
= 0, last
= 0;
1975 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1976 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1979 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1981 /* If the key was invalid give up right-away. */
1984 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1986 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1987 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1989 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1990 if (validated
> 0) {
1991 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1992 "=> Validated from %s to %s, final %s entries not sealed.",
1993 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1994 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1995 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
1996 } else if (last
> 0)
1997 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1998 "=> No sealing yet, %s of entries not sealed.",
1999 FORMAT_TIMESPAN(last
- first
, 0));
2001 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2002 "=> No sealing yet, no entries in file.");
2010 static int simple_varlink_call(const char *option
, const char *method
) {
2011 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2012 const char *error
, *fn
;
2016 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2018 fn
= arg_namespace
?
2019 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2020 "/run/systemd/journal/io.systemd.journal";
2022 r
= varlink_connect_address(&link
, fn
);
2024 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2026 (void) varlink_set_description(link
, "journal");
2027 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2029 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2031 return log_error_errno(r
, "Failed to execute varlink call: %m");
2033 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2034 "Failed to execute varlink call: %s", error
);
2039 static int flush_to_var(void) {
2040 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2041 return 0; /* Already flushed, no need to contact journald */
2042 if (errno
!= ENOENT
)
2043 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2045 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2048 static int relinquish_var(void) {
2049 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2052 static int rotate(void) {
2053 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2056 static int sync_journal(void) {
2057 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2060 static int wait_for_change(sd_journal
*j
, int poll_fd
) {
2061 struct pollfd pollfds
[] = {
2062 { .fd
= poll_fd
, .events
= POLLIN
},
2063 { .fd
= STDOUT_FILENO
},
2069 assert(poll_fd
>= 0);
2071 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
2072 * i.e. when it is closed. */
2074 r
= sd_journal_get_timeout(j
, &timeout
);
2076 return log_error_errno(r
, "Failed to determine journal waiting time: %m");
2078 r
= ppoll_usec(pollfds
, ELEMENTSOF(pollfds
), timeout
);
2082 return log_error_errno(r
, "Couldn't wait for journal event: %m");
2084 if (pollfds
[1].revents
& (POLLHUP
|POLLERR
)) /* STDOUT has been closed? */
2085 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED
),
2086 "Standard output has been closed.");
2088 r
= sd_journal_process(j
);
2090 return log_error_errno(r
, "Failed to process journal events: %m");
2095 static int run(int argc
, char *argv
[]) {
2096 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2097 _cleanup_(umount_and_rmdir_and_freep
) char *unlink_dir
= NULL
;
2098 bool previous_boot_id_valid
= false, first_line
= true, ellipsized
= false, need_seek
= false;
2099 bool use_cursor
= false, after_cursor
= false;
2100 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2101 sd_id128_t previous_boot_id
= SD_ID128_NULL
, previous_boot_id_output
= SD_ID128_NULL
;
2102 dual_timestamp previous_ts_output
= DUAL_TIMESTAMP_NULL
;
2103 _cleanup_close_
int machine_fd
= -EBADF
;
2104 int n_shown
= 0, r
, poll_fd
= -EBADF
;
2106 setlocale(LC_ALL
, "");
2109 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2110 * split up into many files. */
2111 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2113 r
= parse_argv(argc
, argv
);
2120 r
= mount_image_privately_interactively(
2122 DISSECT_IMAGE_GENERIC_ROOT
|
2123 DISSECT_IMAGE_REQUIRE_ROOT
|
2124 DISSECT_IMAGE_VALIDATE_OS
|
2125 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2126 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2132 arg_root
= strdup(unlink_dir
);
2137 signal(SIGWINCH
, columns_lines_cache_reset
);
2140 switch (arg_action
) {
2142 case ACTION_NEW_ID128
:
2143 return id128_print_new(ID128_PRINT_PRETTY
);
2145 case ACTION_SETUP_KEYS
:
2146 return setup_keys();
2148 case ACTION_LIST_CATALOG
:
2149 case ACTION_DUMP_CATALOG
:
2150 case ACTION_UPDATE_CATALOG
: {
2151 _cleanup_free_
char *database
= NULL
;
2153 database
= path_join(arg_root
, CATALOG_DATABASE
);
2157 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2158 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2160 return log_error_errno(r
, "Failed to list catalog: %m");
2162 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2164 pager_open(arg_pager_flags
);
2167 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2169 r
= catalog_list(stdout
, database
, oneline
);
2171 return log_error_errno(r
, "Failed to list catalog: %m");
2178 return flush_to_var();
2180 case ACTION_RELINQUISH_VAR
:
2181 return relinquish_var();
2184 return sync_journal();
2190 case ACTION_PRINT_HEADER
:
2192 case ACTION_DISK_USAGE
:
2193 case ACTION_LIST_BOOTS
:
2195 case ACTION_ROTATE_AND_VACUUM
:
2196 case ACTION_LIST_FIELDS
:
2197 case ACTION_LIST_FIELD_NAMES
:
2198 /* These ones require access to the journal files, continue below. */
2202 assert_not_reached();
2206 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2208 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2209 else if (arg_file_stdin
)
2210 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2212 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2213 else if (arg_machine
) {
2214 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2215 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2216 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2220 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2221 * the container, thus we need root privileges to override them. */
2222 return log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2224 r
= sd_bus_open_system(&bus
);
2226 return log_error_errno(r
, "Failed to open system bus: %m");
2228 r
= sd_bus_call_method(
2230 "org.freedesktop.machine1",
2231 "/org/freedesktop/machine1",
2232 "org.freedesktop.machine1.Manager",
2233 "OpenMachineRootDirectory",
2238 return log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2240 r
= sd_bus_message_read(reply
, "h", &fd
);
2242 return bus_log_parse_error(r
);
2244 machine_fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2246 return log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2248 r
= sd_journal_open_directory_fd(&j
, machine_fd
, SD_JOURNAL_OS_ROOT
);
2250 r
= sd_journal_open_namespace(
2253 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2254 arg_namespace_flags
| arg_journal_type
);
2256 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2258 r
= journal_access_check_and_warn(j
, arg_quiet
,
2259 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2263 switch (arg_action
) {
2265 case ACTION_NEW_ID128
:
2266 case ACTION_SETUP_KEYS
:
2267 case ACTION_LIST_CATALOG
:
2268 case ACTION_DUMP_CATALOG
:
2269 case ACTION_UPDATE_CATALOG
:
2273 assert_not_reached();
2275 case ACTION_PRINT_HEADER
:
2276 journal_print_header(j
);
2280 return verify(j
, !arg_quiet
);
2282 case ACTION_DISK_USAGE
: {
2285 r
= sd_journal_get_usage(j
, &bytes
);
2289 printf("Archived and active journals take up %s in the file system.\n",
2290 FORMAT_BYTES(bytes
));
2295 case ACTION_LIST_BOOTS
:
2296 return list_boots(j
);
2298 case ACTION_ROTATE_AND_VACUUM
:
2306 case ACTION_VACUUM
: {
2310 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2311 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2313 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2322 case ACTION_LIST_FIELD_NAMES
: {
2325 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2326 printf("%s\n", field
);
2332 case ACTION_LIST_FIELDS
:
2336 assert_not_reached();
2339 if (arg_boot_offset
!= 0 &&
2340 sd_journal_has_runtime_files(j
) > 0 &&
2341 sd_journal_has_persistent_files(j
) == 0) {
2342 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2344 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2349 /* add_boot() must be called first!
2350 * It may need to seek the journal to find parent boot IDs. */
2361 return log_error_errno(r
, "Failed to add filter for units: %m");
2363 r
= add_syslog_identifier(j
);
2365 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2367 r
= add_priorities(j
);
2371 r
= add_facilities(j
);
2375 r
= add_matches(j
, argv
+ optind
);
2379 if (DEBUG_LOGGING
) {
2380 _cleanup_free_
char *filter
= NULL
;
2382 filter
= journal_make_match_string(j
);
2386 log_debug("Journal filter: %s", filter
);
2389 if (arg_action
== ACTION_LIST_FIELDS
) {
2395 r
= sd_journal_set_data_threshold(j
, 0);
2397 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2399 r
= sd_journal_query_unique(j
, arg_field
);
2401 return log_error_errno(r
, "Failed to query unique data objects: %m");
2403 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2406 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2409 eq
= memchr(data
, '=', size
);
2411 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2413 printf("%.*s\n", (int) size
, (const char*) data
);
2421 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2423 poll_fd
= sd_journal_get_fd(j
);
2424 if (poll_fd
== -EMFILE
) {
2425 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2427 } else if (poll_fd
== -EMEDIUMTYPE
)
2428 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2429 else if (poll_fd
< 0)
2430 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2433 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2434 _cleanup_free_
char *cursor_from_file
= NULL
;
2435 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2437 if (arg_cursor_file
) {
2438 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2439 if (r
< 0 && r
!= -ENOENT
)
2440 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2443 cursor
= cursor_from_file
;
2444 after_cursor
= true;
2447 after_cursor
= arg_after_cursor
;
2450 r
= sd_journal_seek_cursor(j
, cursor
);
2452 return log_error_errno(r
, "Failed to seek to cursor: %m");
2460 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2462 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2464 if (after_cursor
&& r
< 2) {
2465 /* We couldn't find the next entry after the cursor. */
2472 } else if (arg_since_set
&& !arg_reverse
) {
2473 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2475 return log_error_errno(r
, "Failed to seek to date: %m");
2477 r
= sd_journal_next(j
);
2479 } else if (arg_until_set
&& arg_reverse
) {
2480 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2482 return log_error_errno(r
, "Failed to seek to date: %m");
2484 r
= sd_journal_previous(j
);
2486 } else if (arg_reverse
) {
2487 r
= sd_journal_seek_tail(j
);
2489 return log_error_errno(r
, "Failed to seek to tail: %m");
2491 r
= sd_journal_previous(j
);
2493 } else if (arg_lines
>= 0) {
2494 r
= sd_journal_seek_tail(j
);
2496 return log_error_errno(r
, "Failed to seek to tail: %m");
2498 r
= sd_journal_previous_skip(j
, arg_lines
);
2501 r
= sd_journal_seek_head(j
);
2503 return log_error_errno(r
, "Failed to seek to head: %m");
2505 r
= sd_journal_next(j
);
2508 return log_error_errno(r
, "Failed to iterate through journal: %m");
2513 pager_open(arg_pager_flags
);
2515 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2517 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2519 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2521 return log_error_errno(r
, "Failed to get cutoff: %m");
2524 printf("-- Journal begins at %s. --\n",
2525 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2527 printf("-- Journal begins at %s, ends at %s. --\n",
2528 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2529 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2534 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2536 size_t highlight
[2] = {};
2540 r
= sd_journal_next(j
);
2542 r
= sd_journal_previous(j
);
2544 return log_error_errno(r
, "Failed to iterate through journal: %m");
2549 if (arg_until_set
&& !arg_reverse
) {
2552 r
= sd_journal_get_realtime_usec(j
, &usec
);
2554 return log_error_errno(r
, "Failed to determine timestamp: %m");
2555 if (usec
> arg_until
)
2559 if (arg_since_set
&& arg_reverse
) {
2562 r
= sd_journal_get_realtime_usec(j
, &usec
);
2564 return log_error_errno(r
, "Failed to determine timestamp: %m");
2565 if (usec
< arg_since
)
2569 if (!arg_merge
&& !arg_quiet
) {
2572 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2574 if (previous_boot_id_valid
&&
2575 !sd_id128_equal(boot_id
, previous_boot_id
))
2576 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2577 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2579 previous_boot_id
= boot_id
;
2580 previous_boot_id_valid
= true;
2584 if (arg_compiled_pattern
) {
2585 const void *message
;
2588 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2595 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2598 assert_se(message
= startswith(message
, "MESSAGE="));
2600 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2601 len
- strlen("MESSAGE="), highlight
);
2611 arg_all
* OUTPUT_SHOW_ALL
|
2612 arg_full
* OUTPUT_FULL_WIDTH
|
2613 colors_enabled() * OUTPUT_COLOR
|
2614 arg_catalog
* OUTPUT_CATALOG
|
2615 arg_utc
* OUTPUT_UTC
|
2616 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2618 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2619 arg_output_fields
, highlight
, &ellipsized
,
2620 &previous_ts_output
, &previous_boot_id_output
);
2622 if (r
== -EADDRNOTAVAIL
)
2629 /* If journalctl take a long time to process messages, and during that time journal file
2630 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2631 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2632 * in the "following" case. By periodically calling sd_journal_process() during the processing
2633 * loop we shrink the window of time a client instance has open file descriptors for rotated
2634 * (deleted) journal files. */
2635 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2636 r
= sd_journal_process(j
);
2638 return log_error_errno(r
, "Failed to process inotify events: %m");
2643 if (n_shown
== 0 && !arg_quiet
)
2644 printf("-- No entries --\n");
2650 r
= wait_for_change(j
, poll_fd
);
2657 if (arg_show_cursor
|| arg_cursor_file
) {
2658 _cleanup_free_
char *cursor
= NULL
;
2660 r
= sd_journal_get_cursor(j
, &cursor
);
2661 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2662 return log_error_errno(r
, "Failed to get cursor: %m");
2664 if (arg_show_cursor
)
2665 printf("-- cursor: %s\n", cursor
);
2667 if (arg_cursor_file
) {
2668 r
= write_string_file(arg_cursor_file
, cursor
,
2669 WRITE_STRING_FILE_CREATE
|
2670 WRITE_STRING_FILE_ATOMIC
);
2672 return log_error_errno(r
, "Failed to write new cursor to %s: %m",
2678 if (arg_compiled_pattern
&& n_shown
== 0)
2679 /* --grep was used, no error was thrown, but the pattern didn't
2680 * match anything. Let's mimic grep's behavior here and return
2681 * a non-zero exit code, so journalctl --grep can be used
2682 * in scripts and such */
2688 DEFINE_MAIN_FUNCTION(run
);