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 "memory-util.h"
50 #include "mount-util.h"
51 #include "mountpoint-util.h"
52 #include "nulstr-util.h"
54 #include "parse-argument.h"
55 #include "parse-util.h"
56 #include "path-util.h"
57 #include "pcre2-util.h"
58 #include "pretty-print.h"
59 #include "qrcode-util.h"
60 #include "random-util.h"
61 #include "rlimit-util.h"
64 #include "static-destruct.h"
65 #include "stdio-util.h"
66 #include "string-table.h"
68 #include "syslog-util.h"
69 #include "terminal-util.h"
70 #include "tmpfile-util.h"
71 #include "unit-name.h"
72 #include "user-util.h"
75 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
76 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
79 /* Special values for arg_lines */
80 ARG_LINES_DEFAULT
= -2,
84 static OutputMode arg_output
= OUTPUT_SHORT
;
85 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
86 static bool arg_utc
= false;
87 static bool arg_follow
= false;
88 static bool arg_full
= true;
89 static bool arg_all
= false;
90 static PagerFlags arg_pager_flags
= 0;
91 static int arg_lines
= ARG_LINES_DEFAULT
;
92 static bool arg_no_tail
= false;
93 static bool arg_quiet
= false;
94 static bool arg_merge
= false;
95 static bool arg_boot
= false;
96 static sd_id128_t arg_boot_id
= {};
97 static int arg_boot_offset
= 0;
98 static bool arg_dmesg
= false;
99 static bool arg_no_hostname
= false;
100 static const char *arg_cursor
= NULL
;
101 static const char *arg_cursor_file
= NULL
;
102 static const char *arg_after_cursor
= NULL
;
103 static bool arg_show_cursor
= false;
104 static const char *arg_directory
= NULL
;
105 static char **arg_file
= NULL
;
106 static bool arg_file_stdin
= false;
107 static int arg_priorities
= 0xFF;
108 static Set
*arg_facilities
= NULL
;
109 static char *arg_verify_key
= NULL
;
111 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
112 static bool arg_force
= false;
114 static usec_t arg_since
, arg_until
;
115 static bool arg_since_set
= false, arg_until_set
= false;
116 static char **arg_syslog_identifier
= NULL
;
117 static char **arg_system_units
= NULL
;
118 static char **arg_user_units
= NULL
;
119 static const char *arg_field
= NULL
;
120 static bool arg_catalog
= false;
121 static bool arg_reverse
= false;
122 static int arg_journal_type
= 0;
123 static int arg_namespace_flags
= 0;
124 static char *arg_root
= NULL
;
125 static char *arg_image
= NULL
;
126 static const char *arg_machine
= NULL
;
127 static const char *arg_namespace
= NULL
;
128 static uint64_t arg_vacuum_size
= 0;
129 static uint64_t arg_vacuum_n_files
= 0;
130 static usec_t arg_vacuum_time
= 0;
131 static char **arg_output_fields
= NULL
;
132 static const char *arg_pattern
= NULL
;
133 static pcre2_code
*arg_compiled_pattern
= NULL
;
134 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
136 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
137 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
138 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
139 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
140 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
141 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
142 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
143 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
144 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, strv_freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
156 ACTION_UPDATE_CATALOG
,
159 ACTION_RELINQUISH_VAR
,
163 ACTION_ROTATE_AND_VACUUM
,
165 ACTION_LIST_FIELD_NAMES
,
166 } arg_action
= ACTION_SHOW
;
168 typedef struct BootId
{
172 LIST_FIELDS(struct BootId
, boot_list
);
175 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
176 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
184 if (!path_startswith(devpath
, "/dev/"))
185 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
186 "Devpath does not start with /dev/");
188 if (stat(devpath
, &st
) < 0)
189 return log_error_errno(errno
, "Couldn't stat file: %m");
191 r
= sd_device_new_from_stat_rdev(&device
, &st
);
193 return log_error_errno(r
, "Failed to get device from devnum %u:%u: %m", major(st
.st_rdev
), minor(st
.st_rdev
));
195 for (d
= device
; d
; ) {
196 _cleanup_free_
char *match
= NULL
;
197 const char *subsys
, *sysname
, *devnode
;
200 r
= sd_device_get_subsystem(d
, &subsys
);
204 r
= sd_device_get_sysname(d
, &sysname
);
208 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
212 r
= sd_journal_add_match(j
, match
, 0);
214 return log_error_errno(r
, "Failed to add match: %m");
216 if (sd_device_get_devname(d
, &devnode
) >= 0) {
217 _cleanup_free_
char *match1
= NULL
;
219 r
= stat(devnode
, &st
);
221 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
223 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st
.st_mode
) ? 'b' : 'c', major(st
.st_rdev
), minor(st
.st_rdev
));
227 r
= sd_journal_add_match(j
, match1
, 0);
229 return log_error_errno(r
, "Failed to add match: %m");
233 if (sd_device_get_parent(d
, &parent
) < 0)
239 r
= add_match_this_boot(j
, arg_machine
);
241 return log_error_errno(r
, "Failed to add match for the current boot: %m");
246 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
249 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
251 return format_timestamp(buf
, l
, t
);
254 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
255 sd_id128_t id
= SD_ID128_NULL
;
258 if (streq(x
, "all")) {
259 *boot_id
= SD_ID128_NULL
;
262 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
265 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
266 r
= sd_id128_from_string(t
, &id
);
268 x
+= SD_ID128_STRING_MAX
- 1;
270 if (!IN_SET(*x
, 0, '-', '+'))
274 r
= safe_atoi(x
, &off
);
279 r
= safe_atoi(x
, &off
);
293 static int help_facilities(void) {
295 puts("Available facilities:");
297 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
298 _cleanup_free_
char *t
= NULL
;
300 if (log_facility_unshifted_to_string_alloc(i
, &t
))
308 static int help(void) {
309 _cleanup_free_
char *link
= NULL
;
312 pager_open(arg_pager_flags
);
314 r
= terminal_urlify_man("journalctl", "1", &link
);
318 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
319 "%5$sQuery the journal.%6$s\n\n"
320 "%3$sSource Options:%4$s\n"
321 " --system Show the system journal\n"
322 " --user Show the user journal for the current user\n"
323 " -M --machine=CONTAINER Operate on local container\n"
324 " -m --merge Show entries from all available journals\n"
325 " -D --directory=PATH Show journal files from directory\n"
326 " --file=PATH Show journal file\n"
327 " --root=ROOT Operate on files below a root directory\n"
328 " --image=IMAGE Operate on files in filesystem image\n"
329 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
330 "\n%3$sFiltering Options:%4$s\n"
331 " -S --since=DATE Show entries not older than the specified date\n"
332 " -U --until=DATE Show entries not newer than the specified date\n"
333 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
334 " --after-cursor=CURSOR Show entries after the specified cursor\n"
335 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
336 " -b --boot[=ID] Show current boot or the specified boot\n"
337 " -u --unit=UNIT Show logs from the specified unit\n"
338 " --user-unit=UNIT Show logs from the specified user unit\n"
339 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
340 " -p --priority=RANGE Show entries with the specified priority\n"
341 " --facility=FACILITY... Show entries with the specified facilities\n"
342 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
343 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
344 " -k --dmesg Show kernel message log from the current boot\n"
345 "\n%3$sOutput Control Options:%4$s\n"
346 " -o --output=STRING Change journal output mode (short, short-precise,\n"
347 " short-iso, short-iso-precise, short-full,\n"
348 " short-monotonic, short-unix, verbose, export,\n"
349 " json, json-pretty, json-sse, json-seq, cat,\n"
351 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
352 " -n --lines[=INTEGER] Number of journal entries to show\n"
353 " -r --reverse Show the newest entries first\n"
354 " --show-cursor Print the cursor after all the entries\n"
355 " --utc Express time in Coordinated Universal Time (UTC)\n"
356 " -x --catalog Add message explanations where available\n"
357 " --no-hostname Suppress output of hostname field\n"
358 " --no-full Ellipsize fields\n"
359 " -a --all Show all fields, including long and unprintable\n"
360 " -f --follow Follow the journal\n"
361 " --no-tail Show all lines, even in follow mode\n"
362 " -q --quiet Do not show info messages and privilege warning\n"
363 "\n%3$sPager Control Options:%4$s\n"
364 " --no-pager Do not pipe output into a pager\n"
365 " -e --pager-end Immediately jump to the end in the pager\n"
366 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
367 " --interval=TIME Time interval for changing the FSS sealing key\n"
368 " --verify-key=KEY Specify FSS verification key\n"
369 " --force Override of the FSS key pair with --setup-keys\n"
370 "\n%3$sCommands:%4$s\n"
371 " -h --help Show this help text\n"
372 " --version Show package version\n"
373 " -N --fields List all field names currently used\n"
374 " -F --field=FIELD List all values that a specified field takes\n"
375 " --list-boots Show terse information about recorded boots\n"
376 " --disk-usage Show total disk usage of all journal files\n"
377 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
378 " --vacuum-files=INT Leave only the specified number of journal files\n"
379 " --vacuum-time=TIME Remove journal files older than specified time\n"
380 " --verify Verify journal file consistency\n"
381 " --sync Synchronize unwritten journal messages to disk\n"
382 " --relinquish-var Stop logging to disk, log to temporary file system\n"
383 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
384 " --flush Flush all journal data from /run into /var\n"
385 " --rotate Request immediate rotation of the journal files\n"
386 " --header Show journal header information\n"
387 " --list-catalog Show all message IDs in the catalog\n"
388 " --dump-catalog Show entries in the message catalog\n"
389 " --update-catalog Update the message catalog database\n"
390 " --setup-keys Generate a new FSS key pair\n"
391 "\nSee the %2$s for details.\n",
392 program_invocation_short_name
,
402 static int parse_argv(int argc
, char *argv
[]) {
437 ARG_SMART_RELINQUISH_VAR
,
447 static const struct option options
[] = {
448 { "help", no_argument
, NULL
, 'h' },
449 { "version" , no_argument
, NULL
, ARG_VERSION
},
450 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
451 { "pager-end", no_argument
, NULL
, 'e' },
452 { "follow", no_argument
, NULL
, 'f' },
453 { "force", no_argument
, NULL
, ARG_FORCE
},
454 { "output", required_argument
, NULL
, 'o' },
455 { "all", no_argument
, NULL
, 'a' },
456 { "full", no_argument
, NULL
, 'l' },
457 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
458 { "lines", optional_argument
, NULL
, 'n' },
459 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
460 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
461 { "quiet", no_argument
, NULL
, 'q' },
462 { "merge", no_argument
, NULL
, 'm' },
463 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
464 { "boot", optional_argument
, NULL
, 'b' },
465 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
466 { "dmesg", no_argument
, NULL
, 'k' },
467 { "system", no_argument
, NULL
, ARG_SYSTEM
},
468 { "user", no_argument
, NULL
, ARG_USER
},
469 { "directory", required_argument
, NULL
, 'D' },
470 { "file", required_argument
, NULL
, ARG_FILE
},
471 { "root", required_argument
, NULL
, ARG_ROOT
},
472 { "image", required_argument
, NULL
, ARG_IMAGE
},
473 { "header", no_argument
, NULL
, ARG_HEADER
},
474 { "identifier", required_argument
, NULL
, 't' },
475 { "priority", required_argument
, NULL
, 'p' },
476 { "facility", required_argument
, NULL
, ARG_FACILITY
},
477 { "grep", required_argument
, NULL
, 'g' },
478 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
479 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
480 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
481 { "verify", no_argument
, NULL
, ARG_VERIFY
},
482 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
483 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
484 { "cursor", required_argument
, NULL
, 'c' },
485 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
486 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
487 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
488 { "since", required_argument
, NULL
, 'S' },
489 { "until", required_argument
, NULL
, 'U' },
490 { "unit", required_argument
, NULL
, 'u' },
491 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
492 { "field", required_argument
, NULL
, 'F' },
493 { "fields", no_argument
, NULL
, 'N' },
494 { "catalog", no_argument
, NULL
, 'x' },
495 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
496 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
497 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
498 { "reverse", no_argument
, NULL
, 'r' },
499 { "machine", required_argument
, NULL
, 'M' },
500 { "utc", no_argument
, NULL
, ARG_UTC
},
501 { "flush", no_argument
, NULL
, ARG_FLUSH
},
502 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
503 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
504 { "sync", no_argument
, NULL
, ARG_SYNC
},
505 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
506 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
507 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
508 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
509 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
510 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
511 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
520 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
531 arg_pager_flags
|= PAGER_DISABLE
;
535 arg_pager_flags
|= PAGER_JUMP_TO_END
;
537 if (arg_lines
== ARG_LINES_DEFAULT
)
548 arg_boot_id
= SD_ID128_NULL
;
554 if (streq(optarg
, "help")) {
555 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
559 arg_output
= output_mode_from_string(optarg
);
561 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
563 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
566 if (OUTPUT_MODE_IS_JSON(arg_output
))
567 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
569 arg_json_format_flags
= JSON_FORMAT_OFF
;
587 if (streq(optarg
, "all"))
588 arg_lines
= ARG_LINES_ALL
;
590 r
= safe_atoi(optarg
, &arg_lines
);
591 if (r
< 0 || arg_lines
< 0)
592 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
597 /* Hmm, no argument? Maybe the next
598 * word on the command line is
599 * supposed to be the argument? Let's
600 * see if there is one, and is
604 if (streq(argv
[optind
], "all")) {
605 arg_lines
= ARG_LINES_ALL
;
607 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
621 arg_action
= ACTION_NEW_ID128
;
634 arg_boot_id
= SD_ID128_NULL
;
640 arg_boot_id
= SD_ID128_NULL
;
644 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
646 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
650 /* Hmm, no argument? Maybe the next
651 * word on the command line is
652 * supposed to be the argument? Let's
653 * see if there is one and is parsable
654 * as a boot descriptor... */
655 } else if (optind
< argc
) {
656 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
665 arg_action
= ACTION_LIST_BOOTS
;
669 arg_boot
= arg_dmesg
= true;
673 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
677 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
681 arg_machine
= optarg
;
685 if (streq(optarg
, "*")) {
686 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
687 arg_namespace
= NULL
;
688 } else if (startswith(optarg
, "+")) {
689 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
690 arg_namespace
= optarg
+ 1;
691 } else if (isempty(optarg
)) {
692 arg_namespace_flags
= 0;
693 arg_namespace
= NULL
;
695 arg_namespace_flags
= 0;
696 arg_namespace
= optarg
;
702 arg_directory
= optarg
;
706 if (streq(optarg
, "-"))
707 /* An undocumented feature: we can read journal files from STDIN. We don't document
708 * this though, since after all we only support this for mmap-able, seekable files, and
709 * not for example pipes which are probably the primary usecase for reading things from
710 * STDIN. To avoid confusion we hence don't document this feature. */
711 arg_file_stdin
= true;
713 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
715 return log_error_errno(r
, "Failed to add paths: %m");
720 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
726 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
735 case ARG_CURSOR_FILE
:
736 arg_cursor_file
= optarg
;
739 case ARG_AFTER_CURSOR
:
740 arg_after_cursor
= optarg
;
743 case ARG_SHOW_CURSOR
:
744 arg_show_cursor
= true;
748 arg_action
= ACTION_PRINT_HEADER
;
752 arg_action
= ACTION_VERIFY
;
756 arg_action
= ACTION_DISK_USAGE
;
759 case ARG_VACUUM_SIZE
:
760 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
762 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
764 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
767 case ARG_VACUUM_FILES
:
768 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
770 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
772 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
775 case ARG_VACUUM_TIME
:
776 r
= parse_sec(optarg
, &arg_vacuum_time
);
778 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
780 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
789 arg_action
= ACTION_SETUP_KEYS
;
793 r
= free_and_strdup(&arg_verify_key
, optarg
);
796 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
797 * in ps or htop output. */
798 memset(optarg
, 'x', strlen(optarg
));
800 arg_action
= ACTION_VERIFY
;
805 r
= parse_sec(optarg
, &arg_interval
);
806 if (r
< 0 || arg_interval
<= 0)
807 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
808 "Failed to parse sealing key change interval: %s", optarg
);
815 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
816 "Compiled without forward-secure sealing support.");
822 dots
= strstr(optarg
, "..");
824 _cleanup_free_
char *a
= NULL
;
828 a
= strndup(optarg
, dots
- optarg
);
832 from
= log_level_from_string(a
);
833 to
= log_level_from_string(dots
+ 2);
835 if (from
< 0 || to
< 0)
836 return log_error_errno(from
< 0 ? from
: to
,
837 "Failed to parse log level range %s", optarg
);
842 for (i
= from
; i
<= to
; i
++)
843 arg_priorities
|= 1 << i
;
845 for (i
= to
; i
<= from
; i
++)
846 arg_priorities
|= 1 << i
;
852 p
= log_level_from_string(optarg
);
854 return log_error_errno(p
, "Unknown log level %s", optarg
);
858 for (i
= 0; i
<= p
; i
++)
859 arg_priorities
|= 1 << i
;
869 _cleanup_free_
char *fac
= NULL
;
872 r
= extract_first_word(&p
, &fac
, ",", 0);
874 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
878 if (streq(fac
, "help")) {
883 num
= log_facility_unshifted_from_string(fac
);
885 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
887 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
895 arg_pattern
= optarg
;
898 case ARG_CASE_SENSITIVE
:
900 r
= parse_boolean(optarg
);
902 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
903 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
905 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
910 r
= parse_timestamp(optarg
, &arg_since
);
912 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
913 "Failed to parse timestamp: %s", optarg
);
914 arg_since_set
= true;
918 r
= parse_timestamp(optarg
, &arg_until
);
920 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
921 "Failed to parse timestamp: %s", optarg
);
922 arg_until_set
= true;
926 r
= strv_extend(&arg_syslog_identifier
, optarg
);
932 r
= strv_extend(&arg_system_units
, optarg
);
938 r
= strv_extend(&arg_user_units
, optarg
);
944 arg_action
= ACTION_LIST_FIELDS
;
949 arg_action
= ACTION_LIST_FIELD_NAMES
;
952 case ARG_NO_HOSTNAME
:
953 arg_no_hostname
= true;
960 case ARG_LIST_CATALOG
:
961 arg_action
= ACTION_LIST_CATALOG
;
964 case ARG_DUMP_CATALOG
:
965 arg_action
= ACTION_DUMP_CATALOG
;
968 case ARG_UPDATE_CATALOG
:
969 arg_action
= ACTION_UPDATE_CATALOG
;
981 arg_action
= ACTION_FLUSH
;
984 case ARG_SMART_RELINQUISH_VAR
: {
985 int root_mnt_id
, log_mnt_id
;
987 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
988 * if it's on the same mount as the root file system there's no point in
989 * relinquishing access and we can leave journald write to it until the very last
992 r
= path_get_mnt_id("/", &root_mnt_id
);
994 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
996 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
998 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
999 else if (root_mnt_id
== log_mnt_id
) {
1000 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1003 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1009 case ARG_RELINQUISH_VAR
:
1010 arg_action
= ACTION_RELINQUISH_VAR
;
1014 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1018 arg_action
= ACTION_SYNC
;
1021 case ARG_OUTPUT_FIELDS
: {
1022 _cleanup_strv_free_
char **v
= NULL
;
1024 v
= strv_split(optarg
, ",");
1028 if (!arg_output_fields
)
1029 arg_output_fields
= TAKE_PTR(v
);
1031 r
= strv_extend_strv(&arg_output_fields
, v
, true);
1042 assert_not_reached();
1045 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
1048 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1049 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1050 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1052 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1053 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1054 "--since= must be before --until=.");
1056 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1057 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1058 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1060 if (arg_follow
&& arg_reverse
)
1061 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1062 "Please specify either --reverse= or --follow=, not both.");
1064 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1065 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1066 "Extraneous arguments starting with '%s'",
1069 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1070 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1071 "Using --boot or --list-boots with --merge is not supported.");
1073 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1074 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1075 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1076 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1077 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1081 arg_system_units
= strv_free(arg_system_units
);
1085 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1093 static int add_matches(sd_journal
*j
, char **args
) {
1094 bool have_term
= false;
1098 STRV_FOREACH(i
, args
) {
1101 if (streq(*i
, "+")) {
1104 r
= sd_journal_add_disjunction(j
);
1107 } else if (path_is_absolute(*i
)) {
1108 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1111 r
= chase_symlinks(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1113 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1115 if (lstat(p
, &st
) < 0)
1116 return log_error_errno(errno
, "Couldn't stat file: %m");
1118 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1119 if (executable_is_script(p
, &interpreter
) > 0) {
1120 _cleanup_free_
char *comm
= NULL
;
1122 comm
= strndup(basename(p
), 15);
1126 t
= strjoin("_COMM=", comm
);
1130 /* Append _EXE only if the interpreter is not a link.
1131 Otherwise, it might be outdated often. */
1132 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1133 t2
= strjoin("_EXE=", interpreter
);
1138 t
= strjoin("_EXE=", p
);
1143 r
= sd_journal_add_match(j
, t
, 0);
1146 r
= sd_journal_add_match(j
, t2
, 0);
1148 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1149 r
= add_matches_for_device(j
, p
);
1153 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1154 "File is neither a device node, nor regular file, nor executable: %s",
1159 r
= sd_journal_add_match(j
, *i
, 0);
1164 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1167 if (!strv_isempty(args
) && !have_term
)
1168 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1169 "\"+\" can only be used between terms");
1174 static void boot_id_free_all(BootId
*l
) {
1178 LIST_REMOVE(boot_list
, l
, i
);
1183 static int discover_next_boot(sd_journal
*j
,
1184 sd_id128_t previous_boot_id
,
1188 _cleanup_free_ BootId
*next_boot
= NULL
;
1189 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1196 /* We expect the journal to be on the last position of a boot
1197 * (in relation to the direction we are going), so that the next
1198 * invocation of sd_journal_next/previous will be from a different
1199 * boot. We then collect any information we desire and then jump
1200 * to the last location of the new boot by using a _BOOT_ID match
1201 * coming from the other journal direction. */
1203 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1204 * we can actually advance to a *different* boot. */
1205 sd_journal_flush_matches(j
);
1209 r
= sd_journal_previous(j
);
1211 r
= sd_journal_next(j
);
1215 return 0; /* End of journal, yay. */
1217 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1221 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1222 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1223 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1224 * complete than the main entry array, and hence might reference an entry that's not actually the last
1225 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1226 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1229 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1231 next_boot
= new0(BootId
, 1);
1235 next_boot
->id
= boot_id
;
1237 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1241 /* Now seek to the last occurrence of this boot ID. */
1242 sd_id128_to_string(next_boot
->id
, match
+ STRLEN("_BOOT_ID="));
1243 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1248 r
= sd_journal_seek_head(j
);
1250 r
= sd_journal_seek_tail(j
);
1255 r
= sd_journal_next(j
);
1257 r
= sd_journal_previous(j
);
1261 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1262 "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. */
1264 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1268 *ret
= TAKE_PTR(next_boot
);
1273 static int get_boots(
1276 sd_id128_t
*boot_id
,
1281 BootId
*head
= NULL
, *tail
= NULL
;
1282 const bool advance_older
= boot_id
&& offset
<= 0;
1283 sd_id128_t previous_boot_id
;
1287 /* Adjust for the asymmetry that offset 0 is
1288 * the last (and current) boot, while 1 is considered the
1289 * (chronological) first boot in the journal. */
1290 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1292 /* Advance to the earliest/latest occurrence of our reference
1293 * boot ID (taking our lookup direction into account), so that
1294 * discover_next_boot() can do its job.
1295 * If no reference is given, the journal head/tail will do,
1296 * they're "virtual" boots after all. */
1297 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1298 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1300 sd_journal_flush_matches(j
);
1302 sd_id128_to_string(*boot_id
, match
+ STRLEN("_BOOT_ID="));
1303 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1308 r
= sd_journal_seek_head(j
); /* seek to oldest */
1310 r
= sd_journal_seek_tail(j
); /* seek to newest */
1315 r
= sd_journal_next(j
); /* read the oldest entry */
1317 r
= sd_journal_previous(j
); /* read the most recently added entry */
1322 else if (offset
== 0) {
1327 /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot
1328 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1329 * the following entry, which must then have an older/newer boot ID */
1333 r
= sd_journal_seek_tail(j
); /* seek to newest */
1335 r
= sd_journal_seek_head(j
); /* seek to oldest */
1339 /* No sd_journal_next()/_previous() here.
1341 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1342 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1346 previous_boot_id
= SD_ID128_NULL
;
1348 _cleanup_free_ BootId
*current
= NULL
;
1350 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1352 boot_id_free_all(head
);
1359 previous_boot_id
= current
->id
;
1363 offset
+= advance_older
? 1 : -1;
1368 *boot_id
= current
->id
;
1372 LIST_FOREACH(boot_list
, id
, head
) {
1373 if (sd_id128_equal(id
->id
, current
->id
)) {
1374 /* boot id already stored, something wrong with the journal files */
1375 /* exiting as otherwise this problem would cause forever loop */
1379 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1380 tail
= TAKE_PTR(current
);
1389 sd_journal_flush_matches(j
);
1394 static int list_boots(sd_journal
*j
) {
1395 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1401 count
= get_boots(j
, &all_ids
, NULL
, 0);
1403 return log_error_errno(count
, "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
);
1422 LIST_FOREACH(boot_list
, id
, all_ids
) {
1423 r
= table_add_many(table
,
1424 TABLE_INT
, i
- count
+ 1,
1425 TABLE_SET_ALIGN_PERCENT
, 100,
1426 TABLE_ID128
, id
->id
,
1427 TABLE_TIMESTAMP
, id
->first
,
1428 TABLE_TIMESTAMP
, id
->last
);
1430 return table_log_add_error(r
);
1434 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1436 return table_log_print_error(r
);
1438 boot_id_free_all(all_ids
);
1443 static int add_boot(sd_journal
*j
) {
1444 char match
[STRLEN("_BOOT_ID=") + SD_ID128_STRING_MAX
] = "_BOOT_ID=";
1453 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1454 * We can do this only when we logs are coming from the current machine,
1455 * so take the slow path if log location is specified. */
1456 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1457 !arg_directory
&& !arg_file
&& !arg_root
)
1458 return add_match_this_boot(j
, arg_machine
);
1460 boot_id
= arg_boot_id
;
1461 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1464 const char *reason
= (r
== 0) ? "No such boot ID in journal" : STRERROR(r
);
1466 if (sd_id128_is_null(arg_boot_id
))
1467 log_error("Data from the specified boot (%+i) is not available: %s",
1468 arg_boot_offset
, reason
);
1470 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1471 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1473 return r
== 0 ? -ENODATA
: r
;
1476 sd_id128_to_string(boot_id
, match
+ STRLEN("_BOOT_ID="));
1478 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1480 return log_error_errno(r
, "Failed to add match: %m");
1482 r
= sd_journal_add_conjunction(j
);
1484 return log_error_errno(r
, "Failed to add conjunction: %m");
1489 static int add_dmesg(sd_journal
*j
) {
1496 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1497 STRLEN("_TRANSPORT=kernel"));
1499 return log_error_errno(r
, "Failed to add match: %m");
1501 r
= sd_journal_add_conjunction(j
);
1503 return log_error_errno(r
, "Failed to add conjunction: %m");
1508 static int get_possible_units(
1514 _cleanup_set_free_free_ Set
*found
= NULL
;
1517 found
= set_new(&string_hash_ops
);
1521 NULSTR_FOREACH(field
, fields
) {
1525 r
= sd_journal_query_unique(j
, field
);
1529 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1532 _cleanup_free_
char *u
= NULL
;
1534 eq
= memchr(data
, '=', size
);
1536 prefix
= eq
- (char*) data
+ 1;
1540 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1544 STRV_FOREACH(pattern
, patterns
)
1545 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1546 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1548 r
= set_consume(found
, u
);
1550 if (r
< 0 && r
!= -EEXIST
)
1558 *units
= TAKE_PTR(found
);
1563 /* This list is supposed to return the superset of unit names
1564 * possibly matched by rules added with add_matches_for_unit... */
1565 #define SYSTEM_UNITS \
1569 "OBJECT_SYSTEMD_UNIT\0" \
1572 /* ... and add_matches_for_user_unit */
1573 #define USER_UNITS \
1574 "_SYSTEMD_USER_UNIT\0" \
1576 "COREDUMP_USER_UNIT\0" \
1577 "OBJECT_SYSTEMD_USER_UNIT\0" \
1578 "_SYSTEMD_USER_SLICE\0"
1580 static int add_units(sd_journal
*j
) {
1581 _cleanup_strv_free_
char **patterns
= NULL
;
1586 STRV_FOREACH(i
, arg_system_units
) {
1587 _cleanup_free_
char *u
= NULL
;
1589 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1593 if (string_is_glob(u
)) {
1594 r
= strv_push(&patterns
, u
);
1599 r
= add_matches_for_unit(j
, u
);
1602 r
= sd_journal_add_disjunction(j
);
1609 if (!strv_isempty(patterns
)) {
1610 _cleanup_set_free_free_ Set
*units
= NULL
;
1613 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1617 SET_FOREACH(u
, units
) {
1618 r
= add_matches_for_unit(j
, u
);
1621 r
= sd_journal_add_disjunction(j
);
1628 patterns
= strv_free(patterns
);
1630 STRV_FOREACH(i
, arg_user_units
) {
1631 _cleanup_free_
char *u
= NULL
;
1633 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1637 if (string_is_glob(u
)) {
1638 r
= strv_push(&patterns
, u
);
1643 r
= add_matches_for_user_unit(j
, u
, getuid());
1646 r
= sd_journal_add_disjunction(j
);
1653 if (!strv_isempty(patterns
)) {
1654 _cleanup_set_free_free_ Set
*units
= NULL
;
1657 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1661 SET_FOREACH(u
, units
) {
1662 r
= add_matches_for_user_unit(j
, u
, getuid());
1665 r
= sd_journal_add_disjunction(j
);
1672 /* Complain if the user request matches but nothing whatsoever was
1673 * found, since otherwise everything would be matched. */
1674 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1677 r
= sd_journal_add_conjunction(j
);
1684 static int add_priorities(sd_journal
*j
) {
1685 char match
[] = "PRIORITY=0";
1689 if (arg_priorities
== 0xFF)
1692 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1693 if (arg_priorities
& (1 << i
)) {
1694 match
[sizeof(match
)-2] = '0' + i
;
1696 r
= sd_journal_add_match(j
, match
, strlen(match
));
1698 return log_error_errno(r
, "Failed to add match: %m");
1701 r
= sd_journal_add_conjunction(j
);
1703 return log_error_errno(r
, "Failed to add conjunction: %m");
1708 static int add_facilities(sd_journal
*j
) {
1712 SET_FOREACH(p
, arg_facilities
) {
1713 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1715 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1717 r
= sd_journal_add_match(j
, match
, strlen(match
));
1719 return log_error_errno(r
, "Failed to add match: %m");
1725 static int add_syslog_identifier(sd_journal
*j
) {
1730 STRV_FOREACH(i
, arg_syslog_identifier
) {
1731 _cleanup_free_
char *u
= NULL
;
1733 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1736 r
= sd_journal_add_match(j
, u
, 0);
1739 r
= sd_journal_add_disjunction(j
);
1744 r
= sd_journal_add_conjunction(j
);
1752 static int format_journal_url(
1761 _cleanup_free_
char *url
= NULL
;
1762 _cleanup_fclose_
FILE *f
= NULL
;
1763 size_t url_size
= 0;
1767 assert(seed_size
> 0);
1769 f
= open_memstream_unlocked(&url
, &url_size
);
1776 for (size_t i
= 0; i
< seed_size
; i
++) {
1777 if (i
> 0 && i
% 3 == 0)
1779 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1782 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1785 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1787 fprintf(f
, ";hostname=%s", hn
);
1790 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 int main(int argc
, char *argv
[]) {
2097 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2098 _cleanup_(umount_and_rmdir_and_freep
) char *unlink_dir
= NULL
;
2099 bool previous_boot_id_valid
= false, first_line
= true, ellipsized
= false, need_seek
= 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 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 r
= id128_print_new(ID128_PRINT_PRETTY
);
2146 case ACTION_SETUP_KEYS
:
2150 case ACTION_LIST_CATALOG
:
2151 case ACTION_DUMP_CATALOG
:
2152 case ACTION_UPDATE_CATALOG
: {
2153 _cleanup_free_
char *database
= NULL
;
2155 database
= path_join(arg_root
, CATALOG_DATABASE
);
2161 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2162 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2164 log_error_errno(r
, "Failed to list catalog: %m");
2166 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2168 pager_open(arg_pager_flags
);
2171 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2173 r
= catalog_list(stdout
, database
, oneline
);
2175 log_error_errno(r
, "Failed to list catalog: %m");
2185 case ACTION_RELINQUISH_VAR
:
2186 r
= relinquish_var();
2198 case ACTION_PRINT_HEADER
:
2200 case ACTION_DISK_USAGE
:
2201 case ACTION_LIST_BOOTS
:
2203 case ACTION_ROTATE_AND_VACUUM
:
2204 case ACTION_LIST_FIELDS
:
2205 case ACTION_LIST_FIELD_NAMES
:
2206 /* These ones require access to the journal files, continue below. */
2210 assert_not_reached();
2214 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2216 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2217 else if (arg_file_stdin
)
2218 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2220 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2221 else if (arg_machine
) {
2222 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2223 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2224 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2227 if (geteuid() != 0) {
2228 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2229 * the container, thus we need root privileges to override them. */
2230 r
= log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2234 r
= sd_bus_open_system(&bus
);
2236 log_error_errno(r
, "Failed to open system bus: %m");
2240 r
= sd_bus_call_method(
2242 "org.freedesktop.machine1",
2243 "/org/freedesktop/machine1",
2244 "org.freedesktop.machine1.Manager",
2245 "OpenMachineRootDirectory",
2250 log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2254 r
= sd_bus_message_read(reply
, "h", &fd
);
2256 bus_log_parse_error(r
);
2260 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2262 r
= log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2266 r
= sd_journal_open_directory_fd(&j
, fd
, SD_JOURNAL_OS_ROOT
);
2270 r
= sd_journal_open_namespace(
2273 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2274 arg_namespace_flags
| arg_journal_type
);
2276 log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2280 r
= journal_access_check_and_warn(j
, arg_quiet
,
2281 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2285 switch (arg_action
) {
2287 case ACTION_NEW_ID128
:
2288 case ACTION_SETUP_KEYS
:
2289 case ACTION_LIST_CATALOG
:
2290 case ACTION_DUMP_CATALOG
:
2291 case ACTION_UPDATE_CATALOG
:
2295 assert_not_reached();
2297 case ACTION_PRINT_HEADER
:
2298 journal_print_header(j
);
2303 r
= verify(j
, !arg_quiet
);
2306 case ACTION_DISK_USAGE
: {
2309 r
= sd_journal_get_usage(j
, &bytes
);
2313 printf("Archived and active journals take up %s in the file system.\n",
2314 FORMAT_BYTES(bytes
));
2318 case ACTION_LIST_BOOTS
:
2322 case ACTION_ROTATE_AND_VACUUM
:
2330 case ACTION_VACUUM
: {
2333 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2336 q
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2338 r
= log_error_errno(q
, "Failed to vacuum %s: %m", d
->path
);
2344 case ACTION_LIST_FIELD_NAMES
: {
2347 SD_JOURNAL_FOREACH_FIELD(j
, field
) {
2348 printf("%s\n", field
);
2357 case ACTION_LIST_FIELDS
:
2361 assert_not_reached();
2364 if (arg_boot_offset
!= 0 &&
2365 sd_journal_has_runtime_files(j
) > 0 &&
2366 sd_journal_has_persistent_files(j
) == 0) {
2367 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2371 /* add_boot() must be called first!
2372 * It may need to seek the journal to find parent boot IDs. */
2383 log_error_errno(r
, "Failed to add filter for units: %m");
2387 r
= add_syslog_identifier(j
);
2389 log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2393 r
= add_priorities(j
);
2397 r
= add_facilities(j
);
2401 r
= add_matches(j
, argv
+ optind
);
2405 if (DEBUG_LOGGING
) {
2406 _cleanup_free_
char *filter
= NULL
;
2408 filter
= journal_make_match_string(j
);
2412 log_debug("Journal filter: %s", filter
);
2415 if (arg_action
== ACTION_LIST_FIELDS
) {
2421 r
= sd_journal_set_data_threshold(j
, 0);
2423 log_error_errno(r
, "Failed to unset data size threshold: %m");
2427 r
= sd_journal_query_unique(j
, arg_field
);
2429 log_error_errno(r
, "Failed to query unique data objects: %m");
2433 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2436 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2439 eq
= memchr(data
, '=', size
);
2441 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2443 printf("%.*s\n", (int) size
, (const char*) data
);
2452 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2454 poll_fd
= sd_journal_get_fd(j
);
2455 if (poll_fd
== -EMFILE
) {
2456 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2458 } else if (poll_fd
== -EMEDIUMTYPE
) {
2459 log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2461 } else if (poll_fd
< 0) {
2462 log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2467 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2468 _cleanup_free_
char *cursor_from_file
= NULL
;
2469 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2471 if (arg_cursor_file
) {
2472 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2473 if (r
< 0 && r
!= -ENOENT
) {
2474 log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2479 cursor
= cursor_from_file
;
2480 after_cursor
= true;
2483 after_cursor
= arg_after_cursor
;
2486 r
= sd_journal_seek_cursor(j
, cursor
);
2488 log_error_errno(r
, "Failed to seek to cursor: %m");
2497 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2499 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2501 if (after_cursor
&& r
< 2) {
2502 /* We couldn't find the next entry after the cursor. */
2509 } else if (arg_since_set
&& !arg_reverse
) {
2510 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2512 log_error_errno(r
, "Failed to seek to date: %m");
2515 r
= sd_journal_next(j
);
2517 } else if (arg_until_set
&& arg_reverse
) {
2518 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2520 log_error_errno(r
, "Failed to seek to date: %m");
2523 r
= sd_journal_previous(j
);
2525 } else if (arg_reverse
) {
2526 r
= sd_journal_seek_tail(j
);
2528 log_error_errno(r
, "Failed to seek to tail: %m");
2532 r
= sd_journal_previous(j
);
2534 } else if (arg_lines
>= 0) {
2535 r
= sd_journal_seek_tail(j
);
2537 log_error_errno(r
, "Failed to seek to tail: %m");
2541 r
= sd_journal_previous_skip(j
, arg_lines
);
2544 r
= sd_journal_seek_head(j
);
2546 log_error_errno(r
, "Failed to seek to head: %m");
2550 r
= sd_journal_next(j
);
2554 log_error_errno(r
, "Failed to iterate through journal: %m");
2561 pager_open(arg_pager_flags
);
2563 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2565 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2567 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2569 log_error_errno(r
, "Failed to get cutoff: %m");
2575 printf("-- Journal begins at %s. --\n",
2576 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2578 printf("-- Journal begins at %s, ends at %s. --\n",
2579 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2580 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2585 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2587 size_t highlight
[2] = {};
2591 r
= sd_journal_next(j
);
2593 r
= sd_journal_previous(j
);
2595 log_error_errno(r
, "Failed to iterate through journal: %m");
2602 if (arg_until_set
&& !arg_reverse
) {
2605 r
= sd_journal_get_realtime_usec(j
, &usec
);
2607 log_error_errno(r
, "Failed to determine timestamp: %m");
2610 if (usec
> arg_until
)
2614 if (arg_since_set
&& arg_reverse
) {
2617 r
= sd_journal_get_realtime_usec(j
, &usec
);
2619 log_error_errno(r
, "Failed to determine timestamp: %m");
2622 if (usec
< arg_since
)
2626 if (!arg_merge
&& !arg_quiet
) {
2629 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2631 if (previous_boot_id_valid
&&
2632 !sd_id128_equal(boot_id
, previous_boot_id
))
2633 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2634 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2636 previous_boot_id
= boot_id
;
2637 previous_boot_id_valid
= true;
2641 if (arg_compiled_pattern
) {
2642 const void *message
;
2645 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2652 log_error_errno(r
, "Failed to get MESSAGE field: %m");
2656 assert_se(message
= startswith(message
, "MESSAGE="));
2658 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2659 len
- strlen("MESSAGE="), highlight
);
2669 arg_all
* OUTPUT_SHOW_ALL
|
2670 arg_full
* OUTPUT_FULL_WIDTH
|
2671 colors_enabled() * OUTPUT_COLOR
|
2672 arg_catalog
* OUTPUT_CATALOG
|
2673 arg_utc
* OUTPUT_UTC
|
2674 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2676 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2677 arg_output_fields
, highlight
, &ellipsized
,
2678 &previous_ts_output
, &previous_boot_id_output
);
2680 if (r
== -EADDRNOTAVAIL
)
2687 /* If journalctl take a long time to process messages, and during that time journal file
2688 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2689 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2690 * in the "following" case. By periodically calling sd_journal_process() during the processing
2691 * loop we shrink the window of time a client instance has open file descriptors for rotated
2692 * (deleted) journal files. */
2693 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2694 r
= sd_journal_process(j
);
2696 log_error_errno(r
, "Failed to process inotify events: %m");
2703 if (n_shown
== 0 && !arg_quiet
)
2704 printf("-- No entries --\n");
2710 r
= wait_for_change(j
, poll_fd
);
2717 if (arg_show_cursor
|| arg_cursor_file
) {
2718 _cleanup_free_
char *cursor
= NULL
;
2720 r
= sd_journal_get_cursor(j
, &cursor
);
2721 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2722 log_error_errno(r
, "Failed to get cursor: %m");
2724 if (arg_show_cursor
)
2725 printf("-- cursor: %s\n", cursor
);
2727 if (arg_cursor_file
) {
2728 r
= write_string_file(arg_cursor_file
, cursor
,
2729 WRITE_STRING_FILE_CREATE
|
2730 WRITE_STRING_FILE_ATOMIC
);
2733 "Failed to write new cursor to %s: %m",
2742 if (arg_compiled_pattern
&& r
== 0 && n_shown
== 0)
2743 /* --grep was used, no error was thrown, but the pattern didn't
2744 * match anything. Let's mimic grep's behavior here and return
2745 * a non-zero exit code, so journalctl --grep can be used
2746 * in scripts and such */
2749 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;