2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include <sys/inotify.h>
37 #include "sd-journal.h"
40 #include "alloc-util.h"
41 #include "bus-error.h"
44 #include "chattr-util.h"
49 #include "glob-util.h"
50 #include "hostname-util.h"
52 #include "journal-def.h"
53 #include "journal-internal.h"
54 #include "journal-qrcode.h"
55 #include "journal-vacuum.h"
56 #include "journal-verify.h"
57 #include "locale-util.h"
59 #include "logs-show.h"
62 #include "parse-util.h"
63 #include "path-util.h"
64 #include "rlimit-util.h"
68 #include "syslog-util.h"
69 #include "terminal-util.h"
71 #include "udev-util.h"
72 #include "unit-name.h"
73 #include "user-util.h"
75 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
78 /* Special values for arg_lines */
79 ARG_LINES_DEFAULT
= -2,
83 static OutputMode arg_output
= OUTPUT_SHORT
;
84 static bool arg_utc
= false;
85 static bool arg_pager_end
= false;
86 static bool arg_follow
= false;
87 static bool arg_full
= true;
88 static bool arg_all
= false;
89 static bool arg_no_pager
= false;
90 static int arg_lines
= ARG_LINES_DEFAULT
;
91 static bool arg_no_tail
= false;
92 static bool arg_quiet
= false;
93 static bool arg_merge
= false;
94 static bool arg_boot
= false;
95 static sd_id128_t arg_boot_id
= {};
96 static int arg_boot_offset
= 0;
97 static bool arg_dmesg
= false;
98 static bool arg_no_hostname
= false;
99 static const char *arg_cursor
= NULL
;
100 static const char *arg_after_cursor
= NULL
;
101 static bool arg_show_cursor
= false;
102 static const char *arg_directory
= NULL
;
103 static char **arg_file
= NULL
;
104 static bool arg_file_stdin
= false;
105 static int arg_priorities
= 0xFF;
106 static const char *arg_verify_key
= NULL
;
108 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
109 static bool arg_force
= false;
111 static usec_t arg_since
, arg_until
;
112 static bool arg_since_set
= false, arg_until_set
= false;
113 static char **arg_syslog_identifier
= NULL
;
114 static char **arg_system_units
= NULL
;
115 static char **arg_user_units
= NULL
;
116 static const char *arg_field
= NULL
;
117 static bool arg_catalog
= false;
118 static bool arg_reverse
= false;
119 static int arg_journal_type
= 0;
120 static char *arg_root
= NULL
;
121 static const char *arg_machine
= NULL
;
122 static uint64_t arg_vacuum_size
= 0;
123 static uint64_t arg_vacuum_n_files
= 0;
124 static usec_t arg_vacuum_time
= 0;
135 ACTION_UPDATE_CATALOG
,
142 ACTION_LIST_FIELD_NAMES
,
143 } arg_action
= ACTION_SHOW
;
145 typedef struct BootId
{
149 LIST_FIELDS(struct BootId
, boot_list
);
152 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
154 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
155 _cleanup_udev_device_unref_
struct udev_device
*device
= NULL
;
156 struct udev_device
*d
= NULL
;
162 if (!path_startswith(devpath
, "/dev/")) {
163 log_error("Devpath does not start with /dev/");
171 r
= stat(devpath
, &st
);
173 log_error_errno(errno
, "Couldn't stat file: %m");
175 d
= device
= udev_device_new_from_devnum(udev
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', st
.st_rdev
);
177 return log_error_errno(errno
, "Failed to get udev device from devnum %u:%u: %m", major(st
.st_rdev
), minor(st
.st_rdev
));
180 _cleanup_free_
char *match
= NULL
;
181 const char *subsys
, *sysname
, *devnode
;
183 subsys
= udev_device_get_subsystem(d
);
185 d
= udev_device_get_parent(d
);
189 sysname
= udev_device_get_sysname(d
);
191 d
= udev_device_get_parent(d
);
195 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
, NULL
);
199 r
= sd_journal_add_match(j
, match
, 0);
201 return log_error_errno(r
, "Failed to add match: %m");
203 devnode
= udev_device_get_devnode(d
);
205 _cleanup_free_
char *match1
= NULL
;
207 r
= stat(devnode
, &st
);
209 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
211 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st
.st_mode
) ? 'b' : 'c', major(st
.st_rdev
), minor(st
.st_rdev
));
215 r
= sd_journal_add_match(j
, match1
, 0);
217 return log_error_errno(r
, "Failed to add match: %m");
220 d
= udev_device_get_parent(d
);
223 r
= add_match_this_boot(j
, arg_machine
);
225 return log_error_errno(r
, "Failed to add match for the current boot: %m");
230 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
233 return format_timestamp_utc(buf
, l
, t
);
235 return format_timestamp(buf
, l
, t
);
238 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
239 sd_id128_t id
= SD_ID128_NULL
;
242 if (strlen(x
) >= 32) {
246 r
= sd_id128_from_string(t
, &id
);
250 if (*x
!= '-' && *x
!= '+' && *x
!= 0)
254 r
= safe_atoi(x
, &off
);
259 r
= safe_atoi(x
, &off
);
273 static void help(void) {
275 pager_open(arg_no_pager
, arg_pager_end
);
277 printf("%s [OPTIONS...] [MATCHES...]\n\n"
278 "Query the journal.\n\n"
280 " --system Show the system journal\n"
281 " --user Show the user journal for the current user\n"
282 " -M --machine=CONTAINER Operate on local container\n"
283 " -S --since=DATE Show entries not older than the specified date\n"
284 " -U --until=DATE Show entries not newer than the specified date\n"
285 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
286 " --after-cursor=CURSOR Show entries after the specified cursor\n"
287 " --show-cursor Print the cursor after all the entries\n"
288 " -b --boot[=ID] Show current boot or the specified boot\n"
289 " --list-boots Show terse information about recorded boots\n"
290 " -k --dmesg Show kernel message log from the current boot\n"
291 " -u --unit=UNIT Show logs from the specified unit\n"
292 " --user-unit=UNIT Show logs from the specified user unit\n"
293 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
294 " -p --priority=RANGE Show entries with the specified priority\n"
295 " -e --pager-end Immediately jump to the end in the pager\n"
296 " -f --follow Follow the journal\n"
297 " -n --lines[=INTEGER] Number of journal entries to show\n"
298 " --no-tail Show all lines, even in follow mode\n"
299 " -r --reverse Show the newest entries first\n"
300 " -o --output=STRING Change journal output mode (short, short-iso,\n"
301 " short-precise, short-monotonic, verbose,\n"
302 " export, json, json-pretty, json-sse, cat)\n"
303 " --utc Express time in Coordinated Universal Time (UTC)\n"
304 " -x --catalog Add message explanations where available\n"
305 " --no-full Ellipsize fields\n"
306 " -a --all Show all fields, including long and unprintable\n"
307 " -q --quiet Do not show info messages and privilege warning\n"
308 " --no-pager Do not pipe output into a pager\n"
309 " --no-hostname Suppress output of hostname field\n"
310 " -m --merge Show entries from all available journals\n"
311 " -D --directory=PATH Show journal files from directory\n"
312 " --file=PATH Show journal file\n"
313 " --root=ROOT Operate on catalog files below a root directory\n"
315 " --interval=TIME Time interval for changing the FSS sealing key\n"
316 " --verify-key=KEY Specify FSS verification key\n"
317 " --force Override of the FSS key pair with --setup-keys\n"
320 " -h --help Show this help text\n"
321 " --version Show package version\n"
322 " -N --fields List all field names currently used\n"
323 " -F --field=FIELD List all values that a specified field takes\n"
324 " --disk-usage Show total disk usage of all journal files\n"
325 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
326 " --vacuum-files=INT Leave only the specified number of journal files\n"
327 " --vacuum-time=TIME Remove journal files older than specified time\n"
328 " --verify Verify journal file consistency\n"
329 " --sync Synchronize unwritten journal messages to disk\n"
330 " --flush Flush all journal data from /run into /var\n"
331 " --rotate Request immediate rotation of the journal files\n"
332 " --header Show journal header information\n"
333 " --list-catalog Show all message IDs in the catalog\n"
334 " --dump-catalog Show entries in the message catalog\n"
335 " --update-catalog Update the message catalog database\n"
336 " --new-id128 Generate a new 128-bit ID\n"
338 " --setup-keys Generate a new FSS key pair\n"
340 , program_invocation_short_name
);
343 static int parse_argv(int argc
, char *argv
[]) {
380 static const struct option options
[] = {
381 { "help", no_argument
, NULL
, 'h' },
382 { "version" , no_argument
, NULL
, ARG_VERSION
},
383 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
384 { "pager-end", no_argument
, NULL
, 'e' },
385 { "follow", no_argument
, NULL
, 'f' },
386 { "force", no_argument
, NULL
, ARG_FORCE
},
387 { "output", required_argument
, NULL
, 'o' },
388 { "all", no_argument
, NULL
, 'a' },
389 { "full", no_argument
, NULL
, 'l' },
390 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
391 { "lines", optional_argument
, NULL
, 'n' },
392 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
393 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
},
394 { "quiet", no_argument
, NULL
, 'q' },
395 { "merge", no_argument
, NULL
, 'm' },
396 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
397 { "boot", optional_argument
, NULL
, 'b' },
398 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
399 { "dmesg", no_argument
, NULL
, 'k' },
400 { "system", no_argument
, NULL
, ARG_SYSTEM
},
401 { "user", no_argument
, NULL
, ARG_USER
},
402 { "directory", required_argument
, NULL
, 'D' },
403 { "file", required_argument
, NULL
, ARG_FILE
},
404 { "root", required_argument
, NULL
, ARG_ROOT
},
405 { "header", no_argument
, NULL
, ARG_HEADER
},
406 { "identifier", required_argument
, NULL
, 't' },
407 { "priority", required_argument
, NULL
, 'p' },
408 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
409 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
410 { "verify", no_argument
, NULL
, ARG_VERIFY
},
411 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
412 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
413 { "cursor", required_argument
, NULL
, 'c' },
414 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
415 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
416 { "since", required_argument
, NULL
, 'S' },
417 { "until", required_argument
, NULL
, 'U' },
418 { "unit", required_argument
, NULL
, 'u' },
419 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
420 { "field", required_argument
, NULL
, 'F' },
421 { "fields", no_argument
, NULL
, 'N' },
422 { "catalog", no_argument
, NULL
, 'x' },
423 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
424 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
425 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
426 { "reverse", no_argument
, NULL
, 'r' },
427 { "machine", required_argument
, NULL
, 'M' },
428 { "utc", no_argument
, NULL
, ARG_UTC
},
429 { "flush", no_argument
, NULL
, ARG_FLUSH
},
430 { "sync", no_argument
, NULL
, ARG_SYNC
},
431 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
432 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
433 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
434 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
435 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
444 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
460 arg_pager_end
= true;
462 if (arg_lines
== ARG_LINES_DEFAULT
)
472 arg_output
= output_mode_from_string(optarg
);
473 if (arg_output
< 0) {
474 log_error("Unknown output format '%s'.", optarg
);
478 if (arg_output
== OUTPUT_EXPORT
||
479 arg_output
== OUTPUT_JSON
||
480 arg_output
== OUTPUT_JSON_PRETTY
||
481 arg_output
== OUTPUT_JSON_SSE
||
482 arg_output
== OUTPUT_CAT
)
501 if (streq(optarg
, "all"))
502 arg_lines
= ARG_LINES_ALL
;
504 r
= safe_atoi(optarg
, &arg_lines
);
505 if (r
< 0 || arg_lines
< 0) {
506 log_error("Failed to parse lines '%s'", optarg
);
513 /* Hmm, no argument? Maybe the next
514 * word on the command line is
515 * supposed to be the argument? Let's
516 * see if there is one, and is
520 if (streq(argv
[optind
], "all")) {
521 arg_lines
= ARG_LINES_ALL
;
523 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
537 arg_action
= ACTION_NEW_ID128
;
556 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
558 log_error("Failed to parse boot descriptor '%s'", optarg
);
563 /* Hmm, no argument? Maybe the next
564 * word on the command line is
565 * supposed to be the argument? Let's
566 * see if there is one and is parsable
567 * as a boot descriptor... */
570 parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
) >= 0)
577 arg_action
= ACTION_LIST_BOOTS
;
581 arg_boot
= arg_dmesg
= true;
585 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
589 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
593 arg_machine
= optarg
;
597 arg_directory
= optarg
;
601 if (streq(optarg
, "-"))
602 /* An undocumented feature: we can read journal files from STDIN. We don't document
603 * this though, since after all we only support this for mmap-able, seekable files, and
604 * not for example pipes which are probably the primary usecase for reading things from
605 * STDIN. To avoid confusion we hence don't document this feature. */
606 arg_file_stdin
= true;
608 r
= glob_extend(&arg_file
, optarg
);
610 return log_error_errno(r
, "Failed to add paths: %m");
615 r
= parse_path_argument_and_warn(optarg
, true, &arg_root
);
624 case ARG_AFTER_CURSOR
:
625 arg_after_cursor
= optarg
;
628 case ARG_SHOW_CURSOR
:
629 arg_show_cursor
= true;
633 arg_action
= ACTION_PRINT_HEADER
;
637 arg_action
= ACTION_VERIFY
;
641 arg_action
= ACTION_DISK_USAGE
;
644 case ARG_VACUUM_SIZE
:
645 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
647 log_error("Failed to parse vacuum size: %s", optarg
);
651 arg_action
= ACTION_VACUUM
;
654 case ARG_VACUUM_FILES
:
655 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
657 log_error("Failed to parse vacuum files: %s", optarg
);
661 arg_action
= ACTION_VACUUM
;
664 case ARG_VACUUM_TIME
:
665 r
= parse_sec(optarg
, &arg_vacuum_time
);
667 log_error("Failed to parse vacuum time: %s", optarg
);
671 arg_action
= ACTION_VACUUM
;
680 arg_action
= ACTION_SETUP_KEYS
;
685 arg_action
= ACTION_VERIFY
;
686 arg_verify_key
= optarg
;
691 r
= parse_sec(optarg
, &arg_interval
);
692 if (r
< 0 || arg_interval
<= 0) {
693 log_error("Failed to parse sealing key change interval: %s", optarg
);
702 log_error("Forward-secure sealing not available.");
709 dots
= strstr(optarg
, "..");
715 a
= strndup(optarg
, dots
- optarg
);
719 from
= log_level_from_string(a
);
720 to
= log_level_from_string(dots
+ 2);
723 if (from
< 0 || to
< 0) {
724 log_error("Failed to parse log level range %s", optarg
);
731 for (i
= from
; i
<= to
; i
++)
732 arg_priorities
|= 1 << i
;
734 for (i
= to
; i
<= from
; i
++)
735 arg_priorities
|= 1 << i
;
741 p
= log_level_from_string(optarg
);
743 log_error("Unknown log level %s", optarg
);
749 for (i
= 0; i
<= p
; i
++)
750 arg_priorities
|= 1 << i
;
757 r
= parse_timestamp(optarg
, &arg_since
);
759 log_error("Failed to parse timestamp: %s", optarg
);
762 arg_since_set
= true;
766 r
= parse_timestamp(optarg
, &arg_until
);
768 log_error("Failed to parse timestamp: %s", optarg
);
771 arg_until_set
= true;
775 r
= strv_extend(&arg_syslog_identifier
, optarg
);
781 r
= strv_extend(&arg_system_units
, optarg
);
787 r
= strv_extend(&arg_user_units
, optarg
);
793 arg_action
= ACTION_LIST_FIELDS
;
798 arg_action
= ACTION_LIST_FIELD_NAMES
;
801 case ARG_NO_HOSTNAME
:
802 arg_no_hostname
= true;
809 case ARG_LIST_CATALOG
:
810 arg_action
= ACTION_LIST_CATALOG
;
813 case ARG_DUMP_CATALOG
:
814 arg_action
= ACTION_DUMP_CATALOG
;
817 case ARG_UPDATE_CATALOG
:
818 arg_action
= ACTION_UPDATE_CATALOG
;
830 arg_action
= ACTION_FLUSH
;
834 arg_action
= ACTION_ROTATE
;
838 arg_action
= ACTION_SYNC
;
845 assert_not_reached("Unhandled option");
848 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
851 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
> 1) {
852 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
856 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
) {
857 log_error("--since= must be before --until=.");
861 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1) {
862 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
866 if (arg_follow
&& arg_reverse
) {
867 log_error("Please specify either --reverse= or --follow=, not both.");
871 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
) {
872 log_error("Extraneous arguments starting with '%s'", argv
[optind
]);
876 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
) {
877 log_error("Using --boot or --list-boots with --merge is not supported.");
881 if (!strv_isempty(arg_system_units
) && (arg_journal_type
== SD_JOURNAL_CURRENT_USER
)) {
883 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
884 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
885 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
886 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
890 arg_system_units
= strv_free(arg_system_units
);
896 static int generate_new_id128(void) {
901 r
= sd_id128_randomize(&id
);
903 return log_error_errno(r
, "Failed to generate ID: %m");
905 printf("As string:\n"
906 SD_ID128_FORMAT_STR
"\n\n"
908 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
910 "#define MESSAGE_XYZ SD_ID128_MAKE(",
911 SD_ID128_FORMAT_VAL(id
),
912 SD_ID128_FORMAT_VAL(id
));
913 for (i
= 0; i
< 16; i
++)
914 printf("%02x%s", id
.bytes
[i
], i
!= 15 ? "," : "");
915 fputs(")\n\n", stdout
);
917 printf("As Python constant:\n"
919 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR
"')\n",
920 SD_ID128_FORMAT_VAL(id
));
925 static int add_matches(sd_journal
*j
, char **args
) {
927 bool have_term
= false;
931 STRV_FOREACH(i
, args
) {
934 if (streq(*i
, "+")) {
937 r
= sd_journal_add_disjunction(j
);
940 } else if (path_is_absolute(*i
)) {
941 _cleanup_free_
char *p
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
945 p
= canonicalize_file_name(*i
);
948 if (lstat(path
, &st
) < 0)
949 return log_error_errno(errno
, "Couldn't stat file: %m");
951 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
952 if (executable_is_script(path
, &interpreter
) > 0) {
953 _cleanup_free_
char *comm
;
955 comm
= strndup(basename(path
), 15);
959 t
= strappend("_COMM=", comm
);
963 /* Append _EXE only if the interpreter is not a link.
964 Otherwise, it might be outdated often. */
965 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
966 t2
= strappend("_EXE=", interpreter
);
971 t
= strappend("_EXE=", path
);
976 r
= sd_journal_add_match(j
, t
, 0);
979 r
= sd_journal_add_match(j
, t2
, 0);
981 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
982 r
= add_matches_for_device(j
, path
);
986 log_error("File is neither a device node, nor regular file, nor executable: %s", *i
);
992 r
= sd_journal_add_match(j
, *i
, 0);
997 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1000 if (!strv_isempty(args
) && !have_term
) {
1001 log_error("\"+\" can only be used between terms");
1008 static void boot_id_free_all(BootId
*l
) {
1012 LIST_REMOVE(boot_list
, l
, i
);
1017 static int discover_next_boot(sd_journal
*j
,
1018 sd_id128_t previous_boot_id
,
1022 _cleanup_free_ BootId
*next_boot
= NULL
;
1023 char match
[9+32+1] = "_BOOT_ID=";
1030 /* We expect the journal to be on the last position of a boot
1031 * (in relation to the direction we are going), so that the next
1032 * invocation of sd_journal_next/previous will be from a different
1033 * boot. We then collect any information we desire and then jump
1034 * to the last location of the new boot by using a _BOOT_ID match
1035 * coming from the other journal direction. */
1037 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1038 * we can actually advance to a *different* boot. */
1039 sd_journal_flush_matches(j
);
1043 r
= sd_journal_previous(j
);
1045 r
= sd_journal_next(j
);
1049 return 0; /* End of journal, yay. */
1051 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1055 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1056 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1057 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1058 * complete than the main entry array, and hence might reference an entry that's not actually the last
1059 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1060 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1063 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1065 next_boot
= new0(BootId
, 1);
1069 next_boot
->id
= boot_id
;
1071 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1075 /* Now seek to the last occurrence of this boot ID. */
1076 sd_id128_to_string(next_boot
->id
, match
+ 9);
1077 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1082 r
= sd_journal_seek_head(j
);
1084 r
= sd_journal_seek_tail(j
);
1089 r
= sd_journal_next(j
);
1091 r
= sd_journal_previous(j
);
1095 return -ENODATA
; /* This shouldn't happen. We just came from this very boot ID. */
1097 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1107 static int get_boots(
1110 sd_id128_t
*boot_id
,
1115 BootId
*head
= NULL
, *tail
= NULL
;
1116 const bool advance_older
= boot_id
&& offset
<= 0;
1117 sd_id128_t previous_boot_id
;
1121 /* Adjust for the asymmetry that offset 0 is
1122 * the last (and current) boot, while 1 is considered the
1123 * (chronological) first boot in the journal. */
1124 skip_once
= boot_id
&& sd_id128_is_null(*boot_id
) && offset
<= 0;
1126 /* Advance to the earliest/latest occurrence of our reference
1127 * boot ID (taking our lookup direction into account), so that
1128 * discover_next_boot() can do its job.
1129 * If no reference is given, the journal head/tail will do,
1130 * they're "virtual" boots after all. */
1131 if (boot_id
&& !sd_id128_is_null(*boot_id
)) {
1132 char match
[9+32+1] = "_BOOT_ID=";
1134 sd_journal_flush_matches(j
);
1136 sd_id128_to_string(*boot_id
, match
+ 9);
1137 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1142 r
= sd_journal_seek_head(j
); /* seek to oldest */
1144 r
= sd_journal_seek_tail(j
); /* seek to newest */
1149 r
= sd_journal_next(j
); /* read the oldest entry */
1151 r
= sd_journal_previous(j
); /* read the most recently added entry */
1156 else if (offset
== 0) {
1161 /* At this point the read pointer is positioned at the oldest/newest occurence of the reference boot
1162 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1163 * the following entry, which must then have an older/newer boot ID */
1167 r
= sd_journal_seek_tail(j
); /* seek to newest */
1169 r
= sd_journal_seek_head(j
); /* seek to oldest */
1173 /* No sd_journal_next()/_previous() here.
1175 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1176 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1180 previous_boot_id
= SD_ID128_NULL
;
1182 _cleanup_free_ BootId
*current
= NULL
;
1184 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1186 boot_id_free_all(head
);
1193 previous_boot_id
= current
->id
;
1197 offset
+= advance_older
? 1 : -1;
1202 *boot_id
= current
->id
;
1206 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1217 sd_journal_flush_matches(j
);
1222 static int list_boots(sd_journal
*j
) {
1224 BootId
*id
, *all_ids
;
1228 count
= get_boots(j
, &all_ids
, NULL
, 0);
1230 return log_error_errno(count
, "Failed to determine boots: %m");
1234 pager_open(arg_no_pager
, arg_pager_end
);
1236 /* numbers are one less, but we need an extra char for the sign */
1237 w
= DECIMAL_STR_WIDTH(count
- 1) + 1;
1240 LIST_FOREACH(boot_list
, id
, all_ids
) {
1241 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1243 printf("% *i " SD_ID128_FORMAT_STR
" %s—%s\n",
1245 SD_ID128_FORMAT_VAL(id
->id
),
1246 format_timestamp_maybe_utc(a
, sizeof(a
), id
->first
),
1247 format_timestamp_maybe_utc(b
, sizeof(b
), id
->last
));
1251 boot_id_free_all(all_ids
);
1256 static int add_boot(sd_journal
*j
) {
1257 char match
[9+32+1] = "_BOOT_ID=";
1266 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1267 * We can do this only when we logs are coming from the current machine,
1268 * so take the slow path if log location is specified. */
1269 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1270 !arg_directory
&& !arg_file
)
1272 return add_match_this_boot(j
, arg_machine
);
1274 boot_id
= arg_boot_id
;
1275 r
= get_boots(j
, NULL
, &boot_id
, arg_boot_offset
);
1278 const char *reason
= (r
== 0) ? "No such boot ID in journal" : strerror(-r
);
1280 if (sd_id128_is_null(arg_boot_id
))
1281 log_error("Data from the specified boot (%+i) is not available: %s",
1282 arg_boot_offset
, reason
);
1284 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1285 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1287 return r
== 0 ? -ENODATA
: r
;
1290 sd_id128_to_string(boot_id
, match
+ 9);
1292 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1294 return log_error_errno(r
, "Failed to add match: %m");
1296 r
= sd_journal_add_conjunction(j
);
1298 return log_error_errno(r
, "Failed to add conjunction: %m");
1303 static int add_dmesg(sd_journal
*j
) {
1310 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1312 return log_error_errno(r
, "Failed to add match: %m");
1314 r
= sd_journal_add_conjunction(j
);
1316 return log_error_errno(r
, "Failed to add conjunction: %m");
1321 static int get_possible_units(
1327 _cleanup_set_free_free_ Set
*found
;
1331 found
= set_new(&string_hash_ops
);
1335 NULSTR_FOREACH(field
, fields
) {
1339 r
= sd_journal_query_unique(j
, field
);
1343 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1344 char **pattern
, *eq
;
1346 _cleanup_free_
char *u
= NULL
;
1348 eq
= memchr(data
, '=', size
);
1350 prefix
= eq
- (char*) data
+ 1;
1354 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1358 STRV_FOREACH(pattern
, patterns
)
1359 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1360 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1362 r
= set_consume(found
, u
);
1364 if (r
< 0 && r
!= -EEXIST
)
1377 /* This list is supposed to return the superset of unit names
1378 * possibly matched by rules added with add_matches_for_unit... */
1379 #define SYSTEM_UNITS \
1383 "OBJECT_SYSTEMD_UNIT\0" \
1386 /* ... and add_matches_for_user_unit */
1387 #define USER_UNITS \
1388 "_SYSTEMD_USER_UNIT\0" \
1390 "COREDUMP_USER_UNIT\0" \
1391 "OBJECT_SYSTEMD_USER_UNIT\0"
1393 static int add_units(sd_journal
*j
) {
1394 _cleanup_strv_free_
char **patterns
= NULL
;
1400 STRV_FOREACH(i
, arg_system_units
) {
1401 _cleanup_free_
char *u
= NULL
;
1403 r
= unit_name_mangle(*i
, UNIT_NAME_GLOB
, &u
);
1407 if (string_is_glob(u
)) {
1408 r
= strv_push(&patterns
, u
);
1413 r
= add_matches_for_unit(j
, u
);
1416 r
= sd_journal_add_disjunction(j
);
1423 if (!strv_isempty(patterns
)) {
1424 _cleanup_set_free_free_ Set
*units
= NULL
;
1428 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1432 SET_FOREACH(u
, units
, it
) {
1433 r
= add_matches_for_unit(j
, u
);
1436 r
= sd_journal_add_disjunction(j
);
1443 patterns
= strv_free(patterns
);
1445 STRV_FOREACH(i
, arg_user_units
) {
1446 _cleanup_free_
char *u
= NULL
;
1448 r
= unit_name_mangle(*i
, UNIT_NAME_GLOB
, &u
);
1452 if (string_is_glob(u
)) {
1453 r
= strv_push(&patterns
, u
);
1458 r
= add_matches_for_user_unit(j
, u
, getuid());
1461 r
= sd_journal_add_disjunction(j
);
1468 if (!strv_isempty(patterns
)) {
1469 _cleanup_set_free_free_ Set
*units
= NULL
;
1473 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1477 SET_FOREACH(u
, units
, it
) {
1478 r
= add_matches_for_user_unit(j
, u
, getuid());
1481 r
= sd_journal_add_disjunction(j
);
1488 /* Complain if the user request matches but nothing whatsoever was
1489 * found, since otherwise everything would be matched. */
1490 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1493 r
= sd_journal_add_conjunction(j
);
1500 static int add_priorities(sd_journal
*j
) {
1501 char match
[] = "PRIORITY=0";
1505 if (arg_priorities
== 0xFF)
1508 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1509 if (arg_priorities
& (1 << i
)) {
1510 match
[sizeof(match
)-2] = '0' + i
;
1512 r
= sd_journal_add_match(j
, match
, strlen(match
));
1514 return log_error_errno(r
, "Failed to add match: %m");
1517 r
= sd_journal_add_conjunction(j
);
1519 return log_error_errno(r
, "Failed to add conjunction: %m");
1525 static int add_syslog_identifier(sd_journal
*j
) {
1531 STRV_FOREACH(i
, arg_syslog_identifier
) {
1534 u
= strjoina("SYSLOG_IDENTIFIER=", *i
);
1535 r
= sd_journal_add_match(j
, u
, 0);
1538 r
= sd_journal_add_disjunction(j
);
1543 r
= sd_journal_add_conjunction(j
);
1550 static int setup_keys(void) {
1552 size_t mpk_size
, seed_size
, state_size
, i
;
1553 uint8_t *mpk
, *seed
, *state
;
1555 sd_id128_t machine
, boot
;
1556 char *p
= NULL
, *k
= NULL
;
1561 r
= stat("/var/log/journal", &st
);
1562 if (r
< 0 && errno
!= ENOENT
&& errno
!= ENOTDIR
)
1563 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1565 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1566 log_error("%s is not a directory, must be using persistent logging for FSS.",
1567 "/var/log/journal");
1568 return r
< 0 ? -errno
: -ENOTDIR
;
1571 r
= sd_id128_get_machine(&machine
);
1573 return log_error_errno(r
, "Failed to get machine ID: %m");
1575 r
= sd_id128_get_boot(&boot
);
1577 return log_error_errno(r
, "Failed to get boot ID: %m");
1579 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1580 SD_ID128_FORMAT_VAL(machine
)) < 0)
1585 if (r
< 0 && errno
!= ENOENT
) {
1586 r
= log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1589 } else if (access(p
, F_OK
) >= 0) {
1590 log_error("Sealing key file %s exists already. Use --force to recreate.", p
);
1595 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1596 SD_ID128_FORMAT_VAL(machine
)) < 0) {
1601 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1602 mpk
= alloca(mpk_size
);
1604 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1605 seed
= alloca(seed_size
);
1607 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1608 state
= alloca(state_size
);
1610 fd
= open("/dev/random", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1612 r
= log_error_errno(errno
, "Failed to open /dev/random: %m");
1616 log_info("Generating seed...");
1617 r
= loop_read_exact(fd
, seed
, seed_size
, true);
1619 log_error_errno(r
, "Failed to read random seed: %m");
1623 log_info("Generating key pair...");
1624 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1626 log_info("Generating sealing key...");
1627 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1629 assert(arg_interval
> 0);
1631 n
= now(CLOCK_REALTIME
);
1635 fd
= mkostemp_safe(k
, O_WRONLY
|O_CLOEXEC
);
1637 r
= log_error_errno(fd
, "Failed to open %s: %m", k
);
1641 /* Enable secure remove, exclusion from dump, synchronous
1642 * writing and in-place updating */
1643 r
= chattr_fd(fd
, FS_SECRM_FL
|FS_NODUMP_FL
|FS_SYNC_FL
|FS_NOCOW_FL
, FS_SECRM_FL
|FS_NODUMP_FL
|FS_SYNC_FL
|FS_NOCOW_FL
);
1645 log_warning_errno(r
, "Failed to set file attributes: %m");
1648 memcpy(h
.signature
, "KSHHRHLP", 8);
1649 h
.machine_id
= machine
;
1651 h
.header_size
= htole64(sizeof(h
));
1652 h
.start_usec
= htole64(n
* arg_interval
);
1653 h
.interval_usec
= htole64(arg_interval
);
1654 h
.fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
);
1655 h
.fsprg_state_size
= htole64(state_size
);
1657 r
= loop_write(fd
, &h
, sizeof(h
), false);
1659 log_error_errno(r
, "Failed to write header: %m");
1663 r
= loop_write(fd
, state
, state_size
, false);
1665 log_error_errno(r
, "Failed to write state: %m");
1669 if (link(k
, p
) < 0) {
1670 r
= log_error_errno(errno
, "Failed to link file: %m");
1677 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1678 "the following local file. This key file is automatically updated when the\n"
1679 "sealing key is advanced. It should not be used on multiple hosts.\n"
1683 "Please write down the following %ssecret verification key%s. It should be stored\n"
1684 "at a safe location and should not be saved locally on disk.\n"
1686 ansi_highlight(), ansi_normal(),
1687 ansi_highlight(), ansi_normal(),
1688 ansi_highlight_red(),
1692 for (i
= 0; i
< seed_size
; i
++) {
1693 if (i
> 0 && i
% 3 == 0)
1695 printf("%02x", ((uint8_t*) seed
)[i
]);
1698 printf("/%llx-%llx\n", (unsigned long long) n
, (unsigned long long) arg_interval
);
1701 char tsb
[FORMAT_TIMESPAN_MAX
], *hn
;
1705 "The sealing key is automatically changed every %s.\n",
1707 format_timespan(tsb
, sizeof(tsb
), arg_interval
, 0));
1709 hn
= gethostname_malloc();
1712 hostname_cleanup(hn
);
1713 fprintf(stderr
, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR
".\n", hn
, SD_ID128_FORMAT_VAL(machine
));
1715 fprintf(stderr
, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR
".\n", SD_ID128_FORMAT_VAL(machine
));
1717 #ifdef HAVE_QRENCODE
1718 /* If this is not an UTF-8 system don't print any QR codes */
1719 if (is_locale_utf8()) {
1720 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr
);
1721 print_qr_code(stderr
, seed
, seed_size
, n
, arg_interval
, hn
, machine
);
1741 log_error("Forward-secure sealing not available.");
1746 static int verify(sd_journal
*j
) {
1753 log_show_color(true);
1755 ORDERED_HASHMAP_FOREACH(f
, j
->files
, i
) {
1757 usec_t first
= 0, validated
= 0, last
= 0;
1760 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1761 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1764 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, true);
1766 /* If the key was invalid give up right-away. */
1769 log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1772 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
], c
[FORMAT_TIMESPAN_MAX
];
1773 log_info("PASS: %s", f
->path
);
1775 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1776 if (validated
> 0) {
1777 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1778 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1779 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1780 format_timespan(c
, sizeof(c
), last
> validated
? last
- validated
: 0, 0));
1781 } else if (last
> 0)
1782 log_info("=> No sealing yet, %s of entries not sealed.",
1783 format_timespan(c
, sizeof(c
), last
- first
, 0));
1785 log_info("=> No sealing yet, no entries in file.");
1793 static int access_check_var_log_journal(sd_journal
*j
) {
1795 _cleanup_strv_free_
char **g
= NULL
;
1805 /* If we are root, we should have access, don't warn. */
1809 /* If we are in the 'systemd-journal' group, we should have
1811 r
= in_group("systemd-journal");
1813 return log_error_errno(r
, "Failed to check if we are in the 'systemd-journal' group: %m");
1818 if (laccess("/run/log/journal", F_OK
) >= 0)
1819 dir
= "/run/log/journal";
1821 dir
= "/var/log/journal";
1823 /* If we are in any of the groups listed in the journal ACLs,
1824 * then all is good, too. Let's enumerate all groups from the
1825 * default ACL of the directory, which generally should allow
1826 * access to most journal files too. */
1827 r
= acl_search_groups(dir
, &g
);
1829 return log_error_errno(r
, "Failed to search journal ACL: %m");
1833 /* Print a pretty list, if there were ACLs set. */
1834 if (!strv_isempty(g
)) {
1835 _cleanup_free_
char *s
= NULL
;
1837 /* Thre are groups in the ACL, let's list them */
1838 r
= strv_extend(&g
, "systemd-journal");
1845 s
= strv_join(g
, "', '");
1849 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1850 " Users in groups '%s' can see all messages.\n"
1851 " Pass -q to turn off this notice.", s
);
1856 /* If no ACLs were found, print a short version of the message. */
1857 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1858 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1859 " turn off this notice.");
1864 static int access_check(sd_journal
*j
) {
1872 if (hashmap_isempty(j
->errors
)) {
1873 if (ordered_hashmap_isempty(j
->files
))
1874 log_notice("No journal files were found.");
1879 if (hashmap_contains(j
->errors
, INT_TO_PTR(-EACCES
))) {
1880 (void) access_check_var_log_journal(j
);
1882 if (ordered_hashmap_isempty(j
->files
))
1883 r
= log_error_errno(EACCES
, "No journal files were opened due to insufficient permissions.");
1886 HASHMAP_FOREACH_KEY(path
, code
, j
->errors
, it
) {
1889 err
= abs(PTR_TO_INT(code
));
1896 log_warning_errno(err
, "Journal file %s is truncated, ignoring file.", path
);
1899 case EPROTONOSUPPORT
:
1900 log_warning_errno(err
, "Journal file %s uses an unsupported feature, ignoring file.", path
);
1904 log_warning_errno(err
, "Journal file %s corrupted, ignoring file.", path
);
1908 log_warning_errno(err
, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path
);
1916 static int flush_to_var(void) {
1917 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1918 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1919 _cleanup_close_
int watch_fd
= -1;
1923 log_error("--flush is not supported in conjunction with --machine=.");
1928 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1931 /* OK, let's actually do the full logic, send SIGUSR1 to the
1932 * daemon and set up inotify to wait for the flushed file to appear */
1933 r
= bus_connect_system_systemd(&bus
);
1935 return log_error_errno(r
, "Failed to get D-Bus connection: %m");
1937 r
= sd_bus_call_method(
1939 "org.freedesktop.systemd1",
1940 "/org/freedesktop/systemd1",
1941 "org.freedesktop.systemd1.Manager",
1945 "ssi", "systemd-journald.service", "main", SIGUSR1
);
1947 return log_error_errno(r
, "Failed to kill journal service: %s", bus_error_message(&error
, r
));
1949 mkdir_p("/run/systemd/journal", 0755);
1951 watch_fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
1953 return log_error_errno(errno
, "Failed to create inotify watch: %m");
1955 r
= inotify_add_watch(watch_fd
, "/run/systemd/journal", IN_CREATE
|IN_DONT_FOLLOW
|IN_ONLYDIR
);
1957 return log_error_errno(errno
, "Failed to watch journal directory: %m");
1960 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1963 if (errno
!= ENOENT
)
1964 return log_error_errno(errno
, "Failed to check for existence of /run/systemd/journal/flushed: %m");
1966 r
= fd_wait_for_event(watch_fd
, POLLIN
, USEC_INFINITY
);
1968 return log_error_errno(r
, "Failed to wait for event: %m");
1970 r
= flush_fd(watch_fd
);
1972 return log_error_errno(r
, "Failed to flush inotify events: %m");
1978 static int send_signal_and_wait(int sig
, const char *watch_path
) {
1979 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1980 _cleanup_close_
int watch_fd
= -1;
1985 log_error("--sync and --rotate are not supported in conjunction with --machine=.");
1989 start
= now(CLOCK_MONOTONIC
);
1991 /* This call sends the specified signal to journald, and waits
1992 * for acknowledgment by watching the mtime of the specified
1993 * flag file. This is used to trigger syncing or rotation and
1994 * then wait for the operation to complete. */
1999 /* See if a sync happened by now. */
2000 r
= read_timestamp_file(watch_path
, &tstamp
);
2001 if (r
< 0 && r
!= -ENOENT
)
2002 return log_error_errno(errno
, "Failed to read %s: %m", watch_path
);
2003 if (r
>= 0 && tstamp
>= start
)
2006 /* Let's ask for a sync, but only once. */
2008 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2010 r
= bus_connect_system_systemd(&bus
);
2012 return log_error_errno(r
, "Failed to get D-Bus connection: %m");
2014 r
= sd_bus_call_method(
2016 "org.freedesktop.systemd1",
2017 "/org/freedesktop/systemd1",
2018 "org.freedesktop.systemd1.Manager",
2022 "ssi", "systemd-journald.service", "main", sig
);
2024 return log_error_errno(r
, "Failed to kill journal service: %s", bus_error_message(&error
, r
));
2029 /* Let's install the inotify watch, if we didn't do that yet. */
2032 mkdir_p("/run/systemd/journal", 0755);
2034 watch_fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
2036 return log_error_errno(errno
, "Failed to create inotify watch: %m");
2038 r
= inotify_add_watch(watch_fd
, "/run/systemd/journal", IN_MOVED_TO
|IN_DONT_FOLLOW
|IN_ONLYDIR
);
2040 return log_error_errno(errno
, "Failed to watch journal directory: %m");
2042 /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
2046 /* OK, all preparatory steps done, let's wait until
2047 * inotify reports an event. */
2049 r
= fd_wait_for_event(watch_fd
, POLLIN
, USEC_INFINITY
);
2051 return log_error_errno(r
, "Failed to wait for event: %m");
2053 r
= flush_fd(watch_fd
);
2055 return log_error_errno(r
, "Failed to flush inotify events: %m");
2061 static int rotate(void) {
2062 return send_signal_and_wait(SIGUSR2
, "/run/systemd/journal/rotated");
2065 static int sync_journal(void) {
2066 return send_signal_and_wait(SIGRTMIN
+1, "/run/systemd/journal/synced");
2069 int main(int argc
, char *argv
[]) {
2071 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2072 bool need_seek
= false;
2073 sd_id128_t previous_boot_id
;
2074 bool previous_boot_id_valid
= false, first_line
= true;
2076 bool ellipsized
= false;
2078 setlocale(LC_ALL
, "");
2079 log_parse_environment();
2082 r
= parse_argv(argc
, argv
);
2086 signal(SIGWINCH
, columns_lines_cache_reset
);
2089 /* Increase max number of open files to 16K if we can, we
2090 * might needs this when browsing journal files, which might
2091 * be split up into many files. */
2092 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
2094 switch (arg_action
) {
2096 case ACTION_NEW_ID128
:
2097 r
= generate_new_id128();
2100 case ACTION_SETUP_KEYS
:
2104 case ACTION_LIST_CATALOG
:
2105 case ACTION_DUMP_CATALOG
:
2106 case ACTION_UPDATE_CATALOG
: {
2107 _cleanup_free_
char *database
;
2109 database
= path_join(arg_root
, CATALOG_DATABASE
, NULL
);
2115 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2116 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2118 log_error_errno(r
, "Failed to list catalog: %m");
2120 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2122 pager_open(arg_no_pager
, arg_pager_end
);
2125 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2127 r
= catalog_list(stdout
, database
, oneline
);
2129 log_error_errno(r
, "Failed to list catalog: %m");
2148 case ACTION_PRINT_HEADER
:
2150 case ACTION_DISK_USAGE
:
2151 case ACTION_LIST_BOOTS
:
2153 case ACTION_LIST_FIELDS
:
2154 case ACTION_LIST_FIELD_NAMES
:
2155 /* These ones require access to the journal files, continue below. */
2159 assert_not_reached("Unknown action");
2163 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2164 else if (arg_file_stdin
) {
2165 int ifd
= STDIN_FILENO
;
2166 r
= sd_journal_open_files_fd(&j
, &ifd
, 1, 0);
2167 } else if (arg_file
)
2168 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2169 else if (arg_machine
) {
2170 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2171 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2172 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2175 if (geteuid() != 0) {
2176 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2177 * the container, thus we need root privileges to override them. */
2178 log_error("Using the --machine= switch requires root privileges.");
2183 r
= sd_bus_open_system(&bus
);
2185 log_error_errno(r
, "Failed to open system bus: %m");
2189 r
= sd_bus_call_method(
2191 "org.freedesktop.machine1",
2192 "/org/freedesktop/machine1",
2193 "org.freedesktop.machine1.Manager",
2194 "OpenMachineRootDirectory",
2199 log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2203 r
= sd_bus_message_read(reply
, "h", &fd
);
2205 bus_log_parse_error(r
);
2209 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2211 r
= log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2215 r
= sd_journal_open_directory_fd(&j
, fd
, SD_JOURNAL_OS_ROOT
);
2219 r
= sd_journal_open(&j
, !arg_merge
*SD_JOURNAL_LOCAL_ONLY
+ arg_journal_type
);
2221 log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2225 r
= access_check(j
);
2229 switch (arg_action
) {
2231 case ACTION_NEW_ID128
:
2232 case ACTION_SETUP_KEYS
:
2233 case ACTION_LIST_CATALOG
:
2234 case ACTION_DUMP_CATALOG
:
2235 case ACTION_UPDATE_CATALOG
:
2239 assert_not_reached("Unexpected action.");
2241 case ACTION_PRINT_HEADER
:
2242 journal_print_header(j
);
2250 case ACTION_DISK_USAGE
: {
2252 char sbytes
[FORMAT_BYTES_MAX
];
2254 r
= sd_journal_get_usage(j
, &bytes
);
2258 printf("Archived and active journals take up %s on disk.\n",
2259 format_bytes(sbytes
, sizeof(sbytes
), bytes
));
2263 case ACTION_LIST_BOOTS
:
2267 case ACTION_VACUUM
: {
2271 HASHMAP_FOREACH(d
, j
->directories_by_path
, i
) {
2277 q
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, true);
2279 log_error_errno(q
, "Failed to vacuum %s: %m", d
->path
);
2287 case ACTION_LIST_FIELD_NAMES
: {
2290 SD_JOURNAL_FOREACH_FIELD(j
, field
) {
2291 printf("%s\n", field
);
2300 case ACTION_LIST_FIELDS
:
2304 assert_not_reached("Unknown action");
2307 if (arg_boot_offset
!= 0 &&
2308 sd_journal_has_runtime_files(j
) > 0 &&
2309 sd_journal_has_persistent_files(j
) == 0) {
2310 log_info("Specifying boot ID has no effect, no persistent journal was found");
2314 /* add_boot() must be called first!
2315 * It may need to seek the journal to find parent boot IDs. */
2326 log_error_errno(r
, "Failed to add filter for units: %m");
2330 r
= add_syslog_identifier(j
);
2332 log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2336 r
= add_priorities(j
);
2340 r
= add_matches(j
, argv
+ optind
);
2344 if (_unlikely_(log_get_max_level() >= LOG_DEBUG
)) {
2345 _cleanup_free_
char *filter
;
2347 filter
= journal_make_match_string(j
);
2351 log_debug("Journal filter: %s", filter
);
2354 if (arg_action
== ACTION_LIST_FIELDS
) {
2360 r
= sd_journal_set_data_threshold(j
, 0);
2362 log_error_errno(r
, "Failed to unset data size threshold: %m");
2366 r
= sd_journal_query_unique(j
, arg_field
);
2368 log_error_errno(r
, "Failed to query unique data objects: %m");
2372 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2375 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2378 eq
= memchr(data
, '=', size
);
2380 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2382 printf("%.*s\n", (int) size
, (const char*) data
);
2391 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2393 r
= sd_journal_get_fd(j
);
2394 if (r
== -EMEDIUMTYPE
) {
2395 log_error_errno(r
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2399 log_error_errno(r
, "Failed to get journal fd: %m");
2404 if (arg_cursor
|| arg_after_cursor
) {
2405 r
= sd_journal_seek_cursor(j
, arg_cursor
?: arg_after_cursor
);
2407 log_error_errno(r
, "Failed to seek to cursor: %m");
2412 r
= sd_journal_next_skip(j
, 1 + !!arg_after_cursor
);
2414 r
= sd_journal_previous_skip(j
, 1 + !!arg_after_cursor
);
2416 if (arg_after_cursor
&& r
< 2) {
2417 /* We couldn't find the next entry after the cursor. */
2424 } else if (arg_since_set
&& !arg_reverse
) {
2425 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2427 log_error_errno(r
, "Failed to seek to date: %m");
2430 r
= sd_journal_next(j
);
2432 } else if (arg_until_set
&& arg_reverse
) {
2433 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2435 log_error_errno(r
, "Failed to seek to date: %m");
2438 r
= sd_journal_previous(j
);
2440 } else if (arg_lines
>= 0) {
2441 r
= sd_journal_seek_tail(j
);
2443 log_error_errno(r
, "Failed to seek to tail: %m");
2447 r
= sd_journal_previous_skip(j
, arg_lines
);
2449 } else if (arg_reverse
) {
2450 r
= sd_journal_seek_tail(j
);
2452 log_error_errno(r
, "Failed to seek to tail: %m");
2456 r
= sd_journal_previous(j
);
2459 r
= sd_journal_seek_head(j
);
2461 log_error_errno(r
, "Failed to seek to head: %m");
2465 r
= sd_journal_next(j
);
2469 log_error_errno(r
, "Failed to iterate through journal: %m");
2477 printf("-- No entries --\n");
2483 pager_open(arg_no_pager
, arg_pager_end
);
2487 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2489 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2491 log_error_errno(r
, "Failed to get cutoff: %m");
2497 printf("-- Logs begin at %s. --\n",
2498 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2500 printf("-- Logs begin at %s, end at %s. --\n",
2501 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2502 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2507 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2512 r
= sd_journal_next(j
);
2514 r
= sd_journal_previous(j
);
2516 log_error_errno(r
, "Failed to iterate through journal: %m");
2523 if (arg_until_set
&& !arg_reverse
) {
2526 r
= sd_journal_get_realtime_usec(j
, &usec
);
2528 log_error_errno(r
, "Failed to determine timestamp: %m");
2531 if (usec
> arg_until
)
2535 if (arg_since_set
&& arg_reverse
) {
2538 r
= sd_journal_get_realtime_usec(j
, &usec
);
2540 log_error_errno(r
, "Failed to determine timestamp: %m");
2543 if (usec
< arg_since
)
2547 if (!arg_merge
&& !arg_quiet
) {
2550 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2552 if (previous_boot_id_valid
&&
2553 !sd_id128_equal(boot_id
, previous_boot_id
))
2554 printf("%s-- Reboot --%s\n",
2555 ansi_highlight(), ansi_normal());
2557 previous_boot_id
= boot_id
;
2558 previous_boot_id_valid
= true;
2563 arg_all
* OUTPUT_SHOW_ALL
|
2564 arg_full
* OUTPUT_FULL_WIDTH
|
2565 colors_enabled() * OUTPUT_COLOR
|
2566 arg_catalog
* OUTPUT_CATALOG
|
2567 arg_utc
* OUTPUT_UTC
|
2568 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2570 r
= output_journal(stdout
, j
, arg_output
, 0, flags
, &ellipsized
);
2572 if (r
== -EADDRNOTAVAIL
)
2574 else if (r
< 0 || ferror(stdout
))
2581 if (arg_show_cursor
) {
2582 _cleanup_free_
char *cursor
= NULL
;
2584 r
= sd_journal_get_cursor(j
, &cursor
);
2585 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2586 log_error_errno(r
, "Failed to get cursor: %m");
2588 printf("-- cursor: %s\n", cursor
);
2594 r
= sd_journal_wait(j
, (uint64_t) -1);
2596 log_error_errno(r
, "Couldn't wait for journal event: %m");
2606 strv_free(arg_file
);
2608 strv_free(arg_syslog_identifier
);
2609 strv_free(arg_system_units
);
2610 strv_free(arg_user_units
);
2614 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;