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
[]) {
379 static const struct option options
[] = {
380 { "help", no_argument
, NULL
, 'h' },
381 { "version" , no_argument
, NULL
, ARG_VERSION
},
382 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
383 { "pager-end", no_argument
, NULL
, 'e' },
384 { "follow", no_argument
, NULL
, 'f' },
385 { "force", no_argument
, NULL
, ARG_FORCE
},
386 { "output", required_argument
, NULL
, 'o' },
387 { "all", no_argument
, NULL
, 'a' },
388 { "full", no_argument
, NULL
, 'l' },
389 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
390 { "lines", optional_argument
, NULL
, 'n' },
391 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
392 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
},
393 { "quiet", no_argument
, NULL
, 'q' },
394 { "merge", no_argument
, NULL
, 'm' },
395 { "boot", optional_argument
, NULL
, 'b' },
396 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
397 { "this-boot", optional_argument
, NULL
, 'b' }, /* deprecated */
398 { "dmesg", no_argument
, NULL
, 'k' },
399 { "system", no_argument
, NULL
, ARG_SYSTEM
},
400 { "user", no_argument
, NULL
, ARG_USER
},
401 { "directory", required_argument
, NULL
, 'D' },
402 { "file", required_argument
, NULL
, ARG_FILE
},
403 { "root", required_argument
, NULL
, ARG_ROOT
},
404 { "header", no_argument
, NULL
, ARG_HEADER
},
405 { "identifier", required_argument
, NULL
, 't' },
406 { "priority", required_argument
, NULL
, 'p' },
407 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
408 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
409 { "verify", no_argument
, NULL
, ARG_VERIFY
},
410 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
411 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
412 { "cursor", required_argument
, NULL
, 'c' },
413 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
414 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
415 { "since", required_argument
, NULL
, 'S' },
416 { "until", required_argument
, NULL
, 'U' },
417 { "unit", required_argument
, NULL
, 'u' },
418 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
419 { "field", required_argument
, NULL
, 'F' },
420 { "fields", no_argument
, NULL
, 'N' },
421 { "catalog", no_argument
, NULL
, 'x' },
422 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
423 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
424 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
425 { "reverse", no_argument
, NULL
, 'r' },
426 { "machine", required_argument
, NULL
, 'M' },
427 { "utc", no_argument
, NULL
, ARG_UTC
},
428 { "flush", no_argument
, NULL
, ARG_FLUSH
},
429 { "sync", no_argument
, NULL
, ARG_SYNC
},
430 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
431 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
432 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
433 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
434 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
443 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
459 arg_pager_end
= true;
461 if (arg_lines
== ARG_LINES_DEFAULT
)
471 arg_output
= output_mode_from_string(optarg
);
472 if (arg_output
< 0) {
473 log_error("Unknown output format '%s'.", optarg
);
477 if (arg_output
== OUTPUT_EXPORT
||
478 arg_output
== OUTPUT_JSON
||
479 arg_output
== OUTPUT_JSON_PRETTY
||
480 arg_output
== OUTPUT_JSON_SSE
||
481 arg_output
== OUTPUT_CAT
)
500 if (streq(optarg
, "all"))
501 arg_lines
= ARG_LINES_ALL
;
503 r
= safe_atoi(optarg
, &arg_lines
);
504 if (r
< 0 || arg_lines
< 0) {
505 log_error("Failed to parse lines '%s'", optarg
);
512 /* Hmm, no argument? Maybe the next
513 * word on the command line is
514 * supposed to be the argument? Let's
515 * see if there is one, and is
519 if (streq(argv
[optind
], "all")) {
520 arg_lines
= ARG_LINES_ALL
;
522 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
536 arg_action
= ACTION_NEW_ID128
;
551 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
553 log_error("Failed to parse boot descriptor '%s'", optarg
);
558 /* Hmm, no argument? Maybe the next
559 * word on the command line is
560 * supposed to be the argument? Let's
561 * see if there is one and is parsable
562 * as a boot descriptor... */
565 parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
) >= 0)
572 arg_action
= ACTION_LIST_BOOTS
;
576 arg_boot
= arg_dmesg
= true;
580 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
584 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
588 arg_machine
= optarg
;
592 arg_directory
= optarg
;
596 if (streq(optarg
, "-"))
597 /* An undocumented feature: we can read journal files from STDIN. We don't document
598 * this though, since after all we only support this for mmap-able, seekable files, and
599 * not for example pipes which are probably the primary usecase for reading things from
600 * STDIN. To avoid confusion we hence don't document this feature. */
601 arg_file_stdin
= true;
603 r
= glob_extend(&arg_file
, optarg
);
605 return log_error_errno(r
, "Failed to add paths: %m");
610 r
= parse_path_argument_and_warn(optarg
, true, &arg_root
);
619 case ARG_AFTER_CURSOR
:
620 arg_after_cursor
= optarg
;
623 case ARG_SHOW_CURSOR
:
624 arg_show_cursor
= true;
628 arg_action
= ACTION_PRINT_HEADER
;
632 arg_action
= ACTION_VERIFY
;
636 arg_action
= ACTION_DISK_USAGE
;
639 case ARG_VACUUM_SIZE
:
640 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
642 log_error("Failed to parse vacuum size: %s", optarg
);
646 arg_action
= ACTION_VACUUM
;
649 case ARG_VACUUM_FILES
:
650 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
652 log_error("Failed to parse vacuum files: %s", optarg
);
656 arg_action
= ACTION_VACUUM
;
659 case ARG_VACUUM_TIME
:
660 r
= parse_sec(optarg
, &arg_vacuum_time
);
662 log_error("Failed to parse vacuum time: %s", optarg
);
666 arg_action
= ACTION_VACUUM
;
675 arg_action
= ACTION_SETUP_KEYS
;
680 arg_action
= ACTION_VERIFY
;
681 arg_verify_key
= optarg
;
686 r
= parse_sec(optarg
, &arg_interval
);
687 if (r
< 0 || arg_interval
<= 0) {
688 log_error("Failed to parse sealing key change interval: %s", optarg
);
697 log_error("Forward-secure sealing not available.");
704 dots
= strstr(optarg
, "..");
710 a
= strndup(optarg
, dots
- optarg
);
714 from
= log_level_from_string(a
);
715 to
= log_level_from_string(dots
+ 2);
718 if (from
< 0 || to
< 0) {
719 log_error("Failed to parse log level range %s", optarg
);
726 for (i
= from
; i
<= to
; i
++)
727 arg_priorities
|= 1 << i
;
729 for (i
= to
; i
<= from
; i
++)
730 arg_priorities
|= 1 << i
;
736 p
= log_level_from_string(optarg
);
738 log_error("Unknown log level %s", optarg
);
744 for (i
= 0; i
<= p
; i
++)
745 arg_priorities
|= 1 << i
;
752 r
= parse_timestamp(optarg
, &arg_since
);
754 log_error("Failed to parse timestamp: %s", optarg
);
757 arg_since_set
= true;
761 r
= parse_timestamp(optarg
, &arg_until
);
763 log_error("Failed to parse timestamp: %s", optarg
);
766 arg_until_set
= true;
770 r
= strv_extend(&arg_syslog_identifier
, optarg
);
776 r
= strv_extend(&arg_system_units
, optarg
);
782 r
= strv_extend(&arg_user_units
, optarg
);
788 arg_action
= ACTION_LIST_FIELDS
;
793 arg_action
= ACTION_LIST_FIELD_NAMES
;
796 case ARG_NO_HOSTNAME
:
797 arg_no_hostname
= true;
804 case ARG_LIST_CATALOG
:
805 arg_action
= ACTION_LIST_CATALOG
;
808 case ARG_DUMP_CATALOG
:
809 arg_action
= ACTION_DUMP_CATALOG
;
812 case ARG_UPDATE_CATALOG
:
813 arg_action
= ACTION_UPDATE_CATALOG
;
825 arg_action
= ACTION_FLUSH
;
829 arg_action
= ACTION_ROTATE
;
833 arg_action
= ACTION_SYNC
;
840 assert_not_reached("Unhandled option");
843 if (arg_follow
&& !arg_no_tail
&& !arg_since
&& arg_lines
== ARG_LINES_DEFAULT
)
846 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
> 1) {
847 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
851 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
) {
852 log_error("--since= must be before --until=.");
856 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1) {
857 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
861 if (arg_follow
&& arg_reverse
) {
862 log_error("Please specify either --reverse= or --follow=, not both.");
866 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
) {
867 log_error("Extraneous arguments starting with '%s'", argv
[optind
]);
871 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
) {
872 log_error("Using --boot or --list-boots with --merge is not supported.");
876 if (!strv_isempty(arg_system_units
) && (arg_journal_type
== SD_JOURNAL_CURRENT_USER
)) {
878 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
879 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
880 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
881 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
885 arg_system_units
= strv_free(arg_system_units
);
891 static int generate_new_id128(void) {
896 r
= sd_id128_randomize(&id
);
898 return log_error_errno(r
, "Failed to generate ID: %m");
900 printf("As string:\n"
901 SD_ID128_FORMAT_STR
"\n\n"
903 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
905 "#define MESSAGE_XYZ SD_ID128_MAKE(",
906 SD_ID128_FORMAT_VAL(id
),
907 SD_ID128_FORMAT_VAL(id
));
908 for (i
= 0; i
< 16; i
++)
909 printf("%02x%s", id
.bytes
[i
], i
!= 15 ? "," : "");
910 fputs(")\n\n", stdout
);
912 printf("As Python constant:\n"
914 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR
"')\n",
915 SD_ID128_FORMAT_VAL(id
));
920 static int add_matches(sd_journal
*j
, char **args
) {
922 bool have_term
= false;
926 STRV_FOREACH(i
, args
) {
929 if (streq(*i
, "+")) {
932 r
= sd_journal_add_disjunction(j
);
935 } else if (path_is_absolute(*i
)) {
936 _cleanup_free_
char *p
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
940 p
= canonicalize_file_name(*i
);
943 if (lstat(path
, &st
) < 0)
944 return log_error_errno(errno
, "Couldn't stat file: %m");
946 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
947 if (executable_is_script(path
, &interpreter
) > 0) {
948 _cleanup_free_
char *comm
;
950 comm
= strndup(basename(path
), 15);
954 t
= strappend("_COMM=", comm
);
958 /* Append _EXE only if the interpreter is not a link.
959 Otherwise, it might be outdated often. */
960 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
961 t2
= strappend("_EXE=", interpreter
);
966 t
= strappend("_EXE=", path
);
971 r
= sd_journal_add_match(j
, t
, 0);
974 r
= sd_journal_add_match(j
, t2
, 0);
976 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
977 r
= add_matches_for_device(j
, path
);
981 log_error("File is neither a device node, nor regular file, nor executable: %s", *i
);
987 r
= sd_journal_add_match(j
, *i
, 0);
992 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
995 if (!strv_isempty(args
) && !have_term
) {
996 log_error("\"+\" can only be used between terms");
1003 static void boot_id_free_all(BootId
*l
) {
1007 LIST_REMOVE(boot_list
, l
, i
);
1012 static int discover_next_boot(sd_journal
*j
,
1013 sd_id128_t previous_boot_id
,
1017 _cleanup_free_ BootId
*next_boot
= NULL
;
1018 char match
[9+32+1] = "_BOOT_ID=";
1025 /* We expect the journal to be on the last position of a boot
1026 * (in relation to the direction we are going), so that the next
1027 * invocation of sd_journal_next/previous will be from a different
1028 * boot. We then collect any information we desire and then jump
1029 * to the last location of the new boot by using a _BOOT_ID match
1030 * coming from the other journal direction. */
1032 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1033 * we can actually advance to a *different* boot. */
1034 sd_journal_flush_matches(j
);
1038 r
= sd_journal_previous(j
);
1040 r
= sd_journal_next(j
);
1044 return 0; /* End of journal, yay. */
1046 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
1050 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1051 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1052 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1053 * complete than the main entry array, and hence might reference an entry that's not actually the last
1054 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1055 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1058 } while (sd_id128_equal(boot_id
, previous_boot_id
));
1060 next_boot
= new0(BootId
, 1);
1064 next_boot
->id
= boot_id
;
1066 r
= sd_journal_get_realtime_usec(j
, &next_boot
->first
);
1070 /* Now seek to the last occurrence of this boot ID. */
1071 sd_id128_to_string(next_boot
->id
, match
+ 9);
1072 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1077 r
= sd_journal_seek_head(j
);
1079 r
= sd_journal_seek_tail(j
);
1084 r
= sd_journal_next(j
);
1086 r
= sd_journal_previous(j
);
1090 return -ENODATA
; /* This shouldn't happen. We just came from this very boot ID. */
1092 r
= sd_journal_get_realtime_usec(j
, &next_boot
->last
);
1102 static int get_boots(
1105 sd_id128_t
*query_ref_boot
,
1106 int ref_boot_offset
) {
1110 BootId
*head
= NULL
, *tail
= NULL
;
1111 const bool advance_older
= query_ref_boot
&& ref_boot_offset
<= 0;
1112 sd_id128_t previous_boot_id
;
1116 /* Adjust for the asymmetry that offset 0 is
1117 * the last (and current) boot, while 1 is considered the
1118 * (chronological) first boot in the journal. */
1119 skip_once
= query_ref_boot
&& sd_id128_is_null(*query_ref_boot
) && ref_boot_offset
< 0;
1121 /* Advance to the earliest/latest occurrence of our reference
1122 * boot ID (taking our lookup direction into account), so that
1123 * discover_next_boot() can do its job.
1124 * If no reference is given, the journal head/tail will do,
1125 * they're "virtual" boots after all. */
1126 if (query_ref_boot
&& !sd_id128_is_null(*query_ref_boot
)) {
1127 char match
[9+32+1] = "_BOOT_ID=";
1129 sd_journal_flush_matches(j
);
1131 sd_id128_to_string(*query_ref_boot
, match
+ 9);
1132 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1137 r
= sd_journal_seek_head(j
); /* seek to oldest */
1139 r
= sd_journal_seek_tail(j
); /* seek to newest */
1144 r
= sd_journal_next(j
); /* read the oldest entry */
1146 r
= sd_journal_previous(j
); /* read the most recently added entry */
1151 else if (ref_boot_offset
== 0) {
1156 /* At this point the read pointer is positioned at the oldest/newest occurence of the reference boot
1157 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1158 * the following entry, which must then have an older/newer boot ID */
1162 r
= sd_journal_seek_tail(j
); /* seek to newest */
1164 r
= sd_journal_seek_head(j
); /* seek to oldest */
1168 /* No sd_journal_next()/_previous() here.
1170 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1171 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1175 previous_boot_id
= SD_ID128_NULL
;
1177 _cleanup_free_ BootId
*current
= NULL
;
1179 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, ¤t
);
1181 boot_id_free_all(head
);
1188 previous_boot_id
= current
->id
;
1190 if (query_ref_boot
) {
1192 ref_boot_offset
+= advance_older
? 1 : -1;
1195 if (ref_boot_offset
== 0) {
1197 *query_ref_boot
= current
->id
;
1201 LIST_INSERT_AFTER(boot_list
, head
, tail
, current
);
1212 sd_journal_flush_matches(j
);
1217 static int list_boots(sd_journal
*j
) {
1219 BootId
*id
, *all_ids
;
1223 count
= get_boots(j
, &all_ids
, NULL
, 0);
1225 return log_error_errno(count
, "Failed to determine boots: %m");
1229 pager_open(arg_no_pager
, arg_pager_end
);
1231 /* numbers are one less, but we need an extra char for the sign */
1232 w
= DECIMAL_STR_WIDTH(count
- 1) + 1;
1235 LIST_FOREACH(boot_list
, id
, all_ids
) {
1236 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1238 printf("% *i " SD_ID128_FORMAT_STR
" %s—%s\n",
1240 SD_ID128_FORMAT_VAL(id
->id
),
1241 format_timestamp_maybe_utc(a
, sizeof(a
), id
->first
),
1242 format_timestamp_maybe_utc(b
, sizeof(b
), id
->last
));
1246 boot_id_free_all(all_ids
);
1251 static int add_boot(sd_journal
*j
) {
1252 char match
[9+32+1] = "_BOOT_ID=";
1253 sd_id128_t ref_boot_id
;
1261 if (arg_boot_offset
== 0 && sd_id128_equal(arg_boot_id
, SD_ID128_NULL
))
1262 return add_match_this_boot(j
, arg_machine
);
1264 ref_boot_id
= arg_boot_id
;
1265 r
= get_boots(j
, NULL
, &ref_boot_id
, arg_boot_offset
);
1268 const char *reason
= (r
== 0) ? "No such boot ID in journal" : strerror(-r
);
1270 if (sd_id128_is_null(arg_boot_id
))
1271 log_error("Data from the specified boot (%+i) is not available: %s",
1272 arg_boot_offset
, reason
);
1274 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR
") is not available: %s",
1275 SD_ID128_FORMAT_VAL(arg_boot_id
), reason
);
1277 return r
== 0 ? -ENODATA
: r
;
1280 sd_id128_to_string(ref_boot_id
, match
+ 9);
1282 r
= sd_journal_add_match(j
, match
, sizeof(match
) - 1);
1284 return log_error_errno(r
, "Failed to add match: %m");
1286 r
= sd_journal_add_conjunction(j
);
1288 return log_error_errno(r
, "Failed to add conjunction: %m");
1293 static int add_dmesg(sd_journal
*j
) {
1300 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1302 return log_error_errno(r
, "Failed to add match: %m");
1304 r
= sd_journal_add_conjunction(j
);
1306 return log_error_errno(r
, "Failed to add conjunction: %m");
1311 static int get_possible_units(
1317 _cleanup_set_free_free_ Set
*found
;
1321 found
= set_new(&string_hash_ops
);
1325 NULSTR_FOREACH(field
, fields
) {
1329 r
= sd_journal_query_unique(j
, field
);
1333 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1334 char **pattern
, *eq
;
1336 _cleanup_free_
char *u
= NULL
;
1338 eq
= memchr(data
, '=', size
);
1340 prefix
= eq
- (char*) data
+ 1;
1344 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1348 STRV_FOREACH(pattern
, patterns
)
1349 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1350 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1352 r
= set_consume(found
, u
);
1354 if (r
< 0 && r
!= -EEXIST
)
1367 /* This list is supposed to return the superset of unit names
1368 * possibly matched by rules added with add_matches_for_unit... */
1369 #define SYSTEM_UNITS \
1373 "OBJECT_SYSTEMD_UNIT\0" \
1376 /* ... and add_matches_for_user_unit */
1377 #define USER_UNITS \
1378 "_SYSTEMD_USER_UNIT\0" \
1380 "COREDUMP_USER_UNIT\0" \
1381 "OBJECT_SYSTEMD_USER_UNIT\0"
1383 static int add_units(sd_journal
*j
) {
1384 _cleanup_strv_free_
char **patterns
= NULL
;
1390 STRV_FOREACH(i
, arg_system_units
) {
1391 _cleanup_free_
char *u
= NULL
;
1393 r
= unit_name_mangle(*i
, UNIT_NAME_GLOB
, &u
);
1397 if (string_is_glob(u
)) {
1398 r
= strv_push(&patterns
, u
);
1403 r
= add_matches_for_unit(j
, u
);
1406 r
= sd_journal_add_disjunction(j
);
1413 if (!strv_isempty(patterns
)) {
1414 _cleanup_set_free_free_ Set
*units
= NULL
;
1418 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1422 SET_FOREACH(u
, units
, it
) {
1423 r
= add_matches_for_unit(j
, u
);
1426 r
= sd_journal_add_disjunction(j
);
1433 patterns
= strv_free(patterns
);
1435 STRV_FOREACH(i
, arg_user_units
) {
1436 _cleanup_free_
char *u
= NULL
;
1438 r
= unit_name_mangle(*i
, UNIT_NAME_GLOB
, &u
);
1442 if (string_is_glob(u
)) {
1443 r
= strv_push(&patterns
, u
);
1448 r
= add_matches_for_user_unit(j
, u
, getuid());
1451 r
= sd_journal_add_disjunction(j
);
1458 if (!strv_isempty(patterns
)) {
1459 _cleanup_set_free_free_ Set
*units
= NULL
;
1463 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1467 SET_FOREACH(u
, units
, it
) {
1468 r
= add_matches_for_user_unit(j
, u
, getuid());
1471 r
= sd_journal_add_disjunction(j
);
1478 /* Complain if the user request matches but nothing whatsoever was
1479 * found, since otherwise everything would be matched. */
1480 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1483 r
= sd_journal_add_conjunction(j
);
1490 static int add_priorities(sd_journal
*j
) {
1491 char match
[] = "PRIORITY=0";
1495 if (arg_priorities
== 0xFF)
1498 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1499 if (arg_priorities
& (1 << i
)) {
1500 match
[sizeof(match
)-2] = '0' + i
;
1502 r
= sd_journal_add_match(j
, match
, strlen(match
));
1504 return log_error_errno(r
, "Failed to add match: %m");
1507 r
= sd_journal_add_conjunction(j
);
1509 return log_error_errno(r
, "Failed to add conjunction: %m");
1515 static int add_syslog_identifier(sd_journal
*j
) {
1521 STRV_FOREACH(i
, arg_syslog_identifier
) {
1524 u
= strjoina("SYSLOG_IDENTIFIER=", *i
);
1525 r
= sd_journal_add_match(j
, u
, 0);
1528 r
= sd_journal_add_disjunction(j
);
1533 r
= sd_journal_add_conjunction(j
);
1540 static int setup_keys(void) {
1542 size_t mpk_size
, seed_size
, state_size
, i
;
1543 uint8_t *mpk
, *seed
, *state
;
1545 sd_id128_t machine
, boot
;
1546 char *p
= NULL
, *k
= NULL
;
1551 r
= stat("/var/log/journal", &st
);
1552 if (r
< 0 && errno
!= ENOENT
&& errno
!= ENOTDIR
)
1553 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1555 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1556 log_error("%s is not a directory, must be using persistent logging for FSS.",
1557 "/var/log/journal");
1558 return r
< 0 ? -errno
: -ENOTDIR
;
1561 r
= sd_id128_get_machine(&machine
);
1563 return log_error_errno(r
, "Failed to get machine ID: %m");
1565 r
= sd_id128_get_boot(&boot
);
1567 return log_error_errno(r
, "Failed to get boot ID: %m");
1569 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1570 SD_ID128_FORMAT_VAL(machine
)) < 0)
1575 if (r
< 0 && errno
!= ENOENT
) {
1576 r
= log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1579 } else if (access(p
, F_OK
) >= 0) {
1580 log_error("Sealing key file %s exists already. Use --force to recreate.", p
);
1585 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1586 SD_ID128_FORMAT_VAL(machine
)) < 0) {
1591 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1592 mpk
= alloca(mpk_size
);
1594 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1595 seed
= alloca(seed_size
);
1597 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1598 state
= alloca(state_size
);
1600 fd
= open("/dev/random", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1602 r
= log_error_errno(errno
, "Failed to open /dev/random: %m");
1606 log_info("Generating seed...");
1607 r
= loop_read_exact(fd
, seed
, seed_size
, true);
1609 log_error_errno(r
, "Failed to read random seed: %m");
1613 log_info("Generating key pair...");
1614 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1616 log_info("Generating sealing key...");
1617 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1619 assert(arg_interval
> 0);
1621 n
= now(CLOCK_REALTIME
);
1625 fd
= mkostemp_safe(k
, O_WRONLY
|O_CLOEXEC
);
1627 r
= log_error_errno(fd
, "Failed to open %s: %m", k
);
1631 /* Enable secure remove, exclusion from dump, synchronous
1632 * writing and in-place updating */
1633 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
);
1635 log_warning_errno(r
, "Failed to set file attributes: %m");
1638 memcpy(h
.signature
, "KSHHRHLP", 8);
1639 h
.machine_id
= machine
;
1641 h
.header_size
= htole64(sizeof(h
));
1642 h
.start_usec
= htole64(n
* arg_interval
);
1643 h
.interval_usec
= htole64(arg_interval
);
1644 h
.fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
);
1645 h
.fsprg_state_size
= htole64(state_size
);
1647 r
= loop_write(fd
, &h
, sizeof(h
), false);
1649 log_error_errno(r
, "Failed to write header: %m");
1653 r
= loop_write(fd
, state
, state_size
, false);
1655 log_error_errno(r
, "Failed to write state: %m");
1659 if (link(k
, p
) < 0) {
1660 r
= log_error_errno(errno
, "Failed to link file: %m");
1667 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1668 "the following local file. This key file is automatically updated when the\n"
1669 "sealing key is advanced. It should not be used on multiple hosts.\n"
1673 "Please write down the following %ssecret verification key%s. It should be stored\n"
1674 "at a safe location and should not be saved locally on disk.\n"
1676 ansi_highlight(), ansi_normal(),
1677 ansi_highlight(), ansi_normal(),
1678 ansi_highlight_red(),
1682 for (i
= 0; i
< seed_size
; i
++) {
1683 if (i
> 0 && i
% 3 == 0)
1685 printf("%02x", ((uint8_t*) seed
)[i
]);
1688 printf("/%llx-%llx\n", (unsigned long long) n
, (unsigned long long) arg_interval
);
1691 char tsb
[FORMAT_TIMESPAN_MAX
], *hn
;
1695 "The sealing key is automatically changed every %s.\n",
1697 format_timespan(tsb
, sizeof(tsb
), arg_interval
, 0));
1699 hn
= gethostname_malloc();
1702 hostname_cleanup(hn
);
1703 fprintf(stderr
, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR
".\n", hn
, SD_ID128_FORMAT_VAL(machine
));
1705 fprintf(stderr
, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR
".\n", SD_ID128_FORMAT_VAL(machine
));
1707 #ifdef HAVE_QRENCODE
1708 /* If this is not an UTF-8 system don't print any QR codes */
1709 if (is_locale_utf8()) {
1710 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr
);
1711 print_qr_code(stderr
, seed
, seed_size
, n
, arg_interval
, hn
, machine
);
1731 log_error("Forward-secure sealing not available.");
1736 static int verify(sd_journal
*j
) {
1743 log_show_color(true);
1745 ORDERED_HASHMAP_FOREACH(f
, j
->files
, i
) {
1747 usec_t first
= 0, validated
= 0, last
= 0;
1750 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1751 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1754 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, true);
1756 /* If the key was invalid give up right-away. */
1759 log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1762 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
], c
[FORMAT_TIMESPAN_MAX
];
1763 log_info("PASS: %s", f
->path
);
1765 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1766 if (validated
> 0) {
1767 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1768 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1769 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1770 format_timespan(c
, sizeof(c
), last
> validated
? last
- validated
: 0, 0));
1771 } else if (last
> 0)
1772 log_info("=> No sealing yet, %s of entries not sealed.",
1773 format_timespan(c
, sizeof(c
), last
- first
, 0));
1775 log_info("=> No sealing yet, no entries in file.");
1783 static int access_check_var_log_journal(sd_journal
*j
) {
1785 _cleanup_strv_free_
char **g
= NULL
;
1795 /* If we are root, we should have access, don't warn. */
1799 /* If we are in the 'systemd-journal' group, we should have
1801 r
= in_group("systemd-journal");
1803 return log_error_errno(r
, "Failed to check if we are in the 'systemd-journal' group: %m");
1808 if (laccess("/run/log/journal", F_OK
) >= 0)
1809 dir
= "/run/log/journal";
1811 dir
= "/var/log/journal";
1813 /* If we are in any of the groups listed in the journal ACLs,
1814 * then all is good, too. Let's enumerate all groups from the
1815 * default ACL of the directory, which generally should allow
1816 * access to most journal files too. */
1817 r
= acl_search_groups(dir
, &g
);
1819 return log_error_errno(r
, "Failed to search journal ACL: %m");
1823 /* Print a pretty list, if there were ACLs set. */
1824 if (!strv_isempty(g
)) {
1825 _cleanup_free_
char *s
= NULL
;
1827 /* Thre are groups in the ACL, let's list them */
1828 r
= strv_extend(&g
, "systemd-journal");
1835 s
= strv_join(g
, "', '");
1839 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1840 " Users in groups '%s' can see all messages.\n"
1841 " Pass -q to turn off this notice.", s
);
1846 /* If no ACLs were found, print a short version of the message. */
1847 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1848 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1849 " turn off this notice.");
1854 static int access_check(sd_journal
*j
) {
1862 if (hashmap_isempty(j
->errors
)) {
1863 if (ordered_hashmap_isempty(j
->files
))
1864 log_notice("No journal files were found.");
1869 if (hashmap_contains(j
->errors
, INT_TO_PTR(-EACCES
))) {
1870 (void) access_check_var_log_journal(j
);
1872 if (ordered_hashmap_isempty(j
->files
))
1873 r
= log_error_errno(EACCES
, "No journal files were opened due to insufficient permissions.");
1876 HASHMAP_FOREACH_KEY(path
, code
, j
->errors
, it
) {
1879 err
= abs(PTR_TO_INT(code
));
1886 log_warning_errno(err
, "Journal file %s is truncated, ignoring file.", path
);
1889 case EPROTONOSUPPORT
:
1890 log_warning_errno(err
, "Journal file %s uses an unsupported feature, ignoring file.", path
);
1894 log_warning_errno(err
, "Journal file %s corrupted, ignoring file.", path
);
1898 log_warning_errno(err
, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path
);
1906 static int flush_to_var(void) {
1907 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1908 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1909 _cleanup_close_
int watch_fd
= -1;
1913 log_error("--flush is not supported in conjunction with --machine=.");
1918 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1921 /* OK, let's actually do the full logic, send SIGUSR1 to the
1922 * daemon and set up inotify to wait for the flushed file to appear */
1923 r
= bus_connect_system_systemd(&bus
);
1925 return log_error_errno(r
, "Failed to get D-Bus connection: %m");
1927 r
= sd_bus_call_method(
1929 "org.freedesktop.systemd1",
1930 "/org/freedesktop/systemd1",
1931 "org.freedesktop.systemd1.Manager",
1935 "ssi", "systemd-journald.service", "main", SIGUSR1
);
1937 return log_error_errno(r
, "Failed to kill journal service: %s", bus_error_message(&error
, r
));
1939 mkdir_p("/run/systemd/journal", 0755);
1941 watch_fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
1943 return log_error_errno(errno
, "Failed to create inotify watch: %m");
1945 r
= inotify_add_watch(watch_fd
, "/run/systemd/journal", IN_CREATE
|IN_DONT_FOLLOW
|IN_ONLYDIR
);
1947 return log_error_errno(errno
, "Failed to watch journal directory: %m");
1950 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
1953 if (errno
!= ENOENT
)
1954 return log_error_errno(errno
, "Failed to check for existence of /run/systemd/journal/flushed: %m");
1956 r
= fd_wait_for_event(watch_fd
, POLLIN
, USEC_INFINITY
);
1958 return log_error_errno(r
, "Failed to wait for event: %m");
1960 r
= flush_fd(watch_fd
);
1962 return log_error_errno(r
, "Failed to flush inotify events: %m");
1968 static int send_signal_and_wait(int sig
, const char *watch_path
) {
1969 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1970 _cleanup_close_
int watch_fd
= -1;
1975 log_error("--sync and --rotate are not supported in conjunction with --machine=.");
1979 start
= now(CLOCK_MONOTONIC
);
1981 /* This call sends the specified signal to journald, and waits
1982 * for acknowledgment by watching the mtime of the specified
1983 * flag file. This is used to trigger syncing or rotation and
1984 * then wait for the operation to complete. */
1989 /* See if a sync happened by now. */
1990 r
= read_timestamp_file(watch_path
, &tstamp
);
1991 if (r
< 0 && r
!= -ENOENT
)
1992 return log_error_errno(errno
, "Failed to read %s: %m", watch_path
);
1993 if (r
>= 0 && tstamp
>= start
)
1996 /* Let's ask for a sync, but only once. */
1998 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2000 r
= bus_connect_system_systemd(&bus
);
2002 return log_error_errno(r
, "Failed to get D-Bus connection: %m");
2004 r
= sd_bus_call_method(
2006 "org.freedesktop.systemd1",
2007 "/org/freedesktop/systemd1",
2008 "org.freedesktop.systemd1.Manager",
2012 "ssi", "systemd-journald.service", "main", sig
);
2014 return log_error_errno(r
, "Failed to kill journal service: %s", bus_error_message(&error
, r
));
2019 /* Let's install the inotify watch, if we didn't do that yet. */
2022 mkdir_p("/run/systemd/journal", 0755);
2024 watch_fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
2026 return log_error_errno(errno
, "Failed to create inotify watch: %m");
2028 r
= inotify_add_watch(watch_fd
, "/run/systemd/journal", IN_MOVED_TO
|IN_DONT_FOLLOW
|IN_ONLYDIR
);
2030 return log_error_errno(errno
, "Failed to watch journal directory: %m");
2032 /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
2036 /* OK, all preparatory steps done, let's wait until
2037 * inotify reports an event. */
2039 r
= fd_wait_for_event(watch_fd
, POLLIN
, USEC_INFINITY
);
2041 return log_error_errno(r
, "Failed to wait for event: %m");
2043 r
= flush_fd(watch_fd
);
2045 return log_error_errno(r
, "Failed to flush inotify events: %m");
2051 static int rotate(void) {
2052 return send_signal_and_wait(SIGUSR2
, "/run/systemd/journal/rotated");
2055 static int sync_journal(void) {
2056 return send_signal_and_wait(SIGRTMIN
+1, "/run/systemd/journal/synced");
2059 int main(int argc
, char *argv
[]) {
2061 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2062 bool need_seek
= false;
2063 sd_id128_t previous_boot_id
;
2064 bool previous_boot_id_valid
= false, first_line
= true;
2066 bool ellipsized
= false;
2068 setlocale(LC_ALL
, "");
2069 log_parse_environment();
2072 r
= parse_argv(argc
, argv
);
2076 signal(SIGWINCH
, columns_lines_cache_reset
);
2079 /* Increase max number of open files to 16K if we can, we
2080 * might needs this when browsing journal files, which might
2081 * be split up into many files. */
2082 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
2084 switch (arg_action
) {
2086 case ACTION_NEW_ID128
:
2087 r
= generate_new_id128();
2090 case ACTION_SETUP_KEYS
:
2094 case ACTION_LIST_CATALOG
:
2095 case ACTION_DUMP_CATALOG
:
2096 case ACTION_UPDATE_CATALOG
: {
2097 _cleanup_free_
char *database
;
2099 database
= path_join(arg_root
, CATALOG_DATABASE
, NULL
);
2105 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2106 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2108 log_error_errno(r
, "Failed to list catalog: %m");
2110 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2112 pager_open(arg_no_pager
, arg_pager_end
);
2115 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2117 r
= catalog_list(stdout
, database
, oneline
);
2119 log_error_errno(r
, "Failed to list catalog: %m");
2138 case ACTION_PRINT_HEADER
:
2140 case ACTION_DISK_USAGE
:
2141 case ACTION_LIST_BOOTS
:
2143 case ACTION_LIST_FIELDS
:
2144 case ACTION_LIST_FIELD_NAMES
:
2145 /* These ones require access to the journal files, continue below. */
2149 assert_not_reached("Unknown action");
2153 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2154 else if (arg_file_stdin
) {
2155 int ifd
= STDIN_FILENO
;
2156 r
= sd_journal_open_files_fd(&j
, &ifd
, 1, 0);
2157 } else if (arg_file
)
2158 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2159 else if (arg_machine
) {
2160 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2161 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2162 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2165 if (geteuid() != 0) {
2166 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2167 * the container, thus we need root privileges to override them. */
2168 log_error("Using the --machine= switch requires root privileges.");
2173 r
= sd_bus_open_system(&bus
);
2175 log_error_errno(r
, "Failed to open system bus: %m");
2179 r
= sd_bus_call_method(
2181 "org.freedesktop.machine1",
2182 "/org/freedesktop/machine1",
2183 "org.freedesktop.machine1.Manager",
2184 "OpenMachineRootDirectory",
2189 log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2193 r
= sd_bus_message_read(reply
, "h", &fd
);
2195 bus_log_parse_error(r
);
2199 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2201 r
= log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2205 r
= sd_journal_open_directory_fd(&j
, fd
, SD_JOURNAL_OS_ROOT
);
2209 r
= sd_journal_open(&j
, !arg_merge
*SD_JOURNAL_LOCAL_ONLY
+ arg_journal_type
);
2211 log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2215 r
= access_check(j
);
2219 switch (arg_action
) {
2221 case ACTION_NEW_ID128
:
2222 case ACTION_SETUP_KEYS
:
2223 case ACTION_LIST_CATALOG
:
2224 case ACTION_DUMP_CATALOG
:
2225 case ACTION_UPDATE_CATALOG
:
2229 assert_not_reached("Unexpected action.");
2231 case ACTION_PRINT_HEADER
:
2232 journal_print_header(j
);
2240 case ACTION_DISK_USAGE
: {
2242 char sbytes
[FORMAT_BYTES_MAX
];
2244 r
= sd_journal_get_usage(j
, &bytes
);
2248 printf("Archived and active journals take up %s on disk.\n",
2249 format_bytes(sbytes
, sizeof(sbytes
), bytes
));
2253 case ACTION_LIST_BOOTS
:
2257 case ACTION_VACUUM
: {
2261 HASHMAP_FOREACH(d
, j
->directories_by_path
, i
) {
2267 q
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, true);
2269 log_error_errno(q
, "Failed to vacuum %s: %m", d
->path
);
2277 case ACTION_LIST_FIELD_NAMES
: {
2280 SD_JOURNAL_FOREACH_FIELD(j
, field
) {
2281 printf("%s\n", field
);
2290 case ACTION_LIST_FIELDS
:
2294 assert_not_reached("Unknown action");
2297 if (arg_boot_offset
!= 0 &&
2298 sd_journal_has_runtime_files(j
) > 0 &&
2299 sd_journal_has_persistent_files(j
) == 0) {
2300 log_info("Specifying boot ID has no effect, no persistent journal was found");
2304 /* add_boot() must be called first!
2305 * It may need to seek the journal to find parent boot IDs. */
2316 log_error_errno(r
, "Failed to add filter for units: %m");
2320 r
= add_syslog_identifier(j
);
2322 log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2326 r
= add_priorities(j
);
2330 r
= add_matches(j
, argv
+ optind
);
2334 if (_unlikely_(log_get_max_level() >= LOG_DEBUG
)) {
2335 _cleanup_free_
char *filter
;
2337 filter
= journal_make_match_string(j
);
2341 log_debug("Journal filter: %s", filter
);
2344 if (arg_action
== ACTION_LIST_FIELDS
) {
2350 r
= sd_journal_set_data_threshold(j
, 0);
2352 log_error_errno(r
, "Failed to unset data size threshold: %m");
2356 r
= sd_journal_query_unique(j
, arg_field
);
2358 log_error_errno(r
, "Failed to query unique data objects: %m");
2362 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2365 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2368 eq
= memchr(data
, '=', size
);
2370 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2372 printf("%.*s\n", (int) size
, (const char*) data
);
2381 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2383 r
= sd_journal_get_fd(j
);
2384 if (r
== -EMEDIUMTYPE
) {
2385 log_error_errno(r
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2389 log_error_errno(r
, "Failed to get journal fd: %m");
2394 if (arg_cursor
|| arg_after_cursor
) {
2395 r
= sd_journal_seek_cursor(j
, arg_cursor
?: arg_after_cursor
);
2397 log_error_errno(r
, "Failed to seek to cursor: %m");
2402 r
= sd_journal_next_skip(j
, 1 + !!arg_after_cursor
);
2404 r
= sd_journal_previous_skip(j
, 1 + !!arg_after_cursor
);
2406 if (arg_after_cursor
&& r
< 2) {
2407 /* We couldn't find the next entry after the cursor. */
2414 } else if (arg_since_set
&& !arg_reverse
) {
2415 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2417 log_error_errno(r
, "Failed to seek to date: %m");
2420 r
= sd_journal_next(j
);
2422 } else if (arg_until_set
&& arg_reverse
) {
2423 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2425 log_error_errno(r
, "Failed to seek to date: %m");
2428 r
= sd_journal_previous(j
);
2430 } else if (arg_lines
>= 0) {
2431 r
= sd_journal_seek_tail(j
);
2433 log_error_errno(r
, "Failed to seek to tail: %m");
2437 r
= sd_journal_previous_skip(j
, arg_lines
);
2439 } else if (arg_reverse
) {
2440 r
= sd_journal_seek_tail(j
);
2442 log_error_errno(r
, "Failed to seek to tail: %m");
2446 r
= sd_journal_previous(j
);
2449 r
= sd_journal_seek_head(j
);
2451 log_error_errno(r
, "Failed to seek to head: %m");
2455 r
= sd_journal_next(j
);
2459 log_error_errno(r
, "Failed to iterate through journal: %m");
2467 printf("-- No entries --\n");
2473 pager_open(arg_no_pager
, arg_pager_end
);
2477 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2479 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2481 log_error_errno(r
, "Failed to get cutoff: %m");
2487 printf("-- Logs begin at %s. --\n",
2488 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2490 printf("-- Logs begin at %s, end at %s. --\n",
2491 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2492 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2497 while (arg_lines
< 0 || n_shown
< arg_lines
|| (arg_follow
&& !first_line
)) {
2502 r
= sd_journal_next(j
);
2504 r
= sd_journal_previous(j
);
2506 log_error_errno(r
, "Failed to iterate through journal: %m");
2513 if (arg_until_set
&& !arg_reverse
) {
2516 r
= sd_journal_get_realtime_usec(j
, &usec
);
2518 log_error_errno(r
, "Failed to determine timestamp: %m");
2521 if (usec
> arg_until
)
2525 if (arg_since_set
&& arg_reverse
) {
2528 r
= sd_journal_get_realtime_usec(j
, &usec
);
2530 log_error_errno(r
, "Failed to determine timestamp: %m");
2533 if (usec
< arg_since
)
2537 if (!arg_merge
&& !arg_quiet
) {
2540 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2542 if (previous_boot_id_valid
&&
2543 !sd_id128_equal(boot_id
, previous_boot_id
))
2544 printf("%s-- Reboot --%s\n",
2545 ansi_highlight(), ansi_normal());
2547 previous_boot_id
= boot_id
;
2548 previous_boot_id_valid
= true;
2553 arg_all
* OUTPUT_SHOW_ALL
|
2554 arg_full
* OUTPUT_FULL_WIDTH
|
2555 colors_enabled() * OUTPUT_COLOR
|
2556 arg_catalog
* OUTPUT_CATALOG
|
2557 arg_utc
* OUTPUT_UTC
|
2558 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2560 r
= output_journal(stdout
, j
, arg_output
, 0, flags
, &ellipsized
);
2562 if (r
== -EADDRNOTAVAIL
)
2564 else if (r
< 0 || ferror(stdout
))
2571 if (arg_show_cursor
) {
2572 _cleanup_free_
char *cursor
= NULL
;
2574 r
= sd_journal_get_cursor(j
, &cursor
);
2575 if (r
< 0 && r
!= -EADDRNOTAVAIL
)
2576 log_error_errno(r
, "Failed to get cursor: %m");
2578 printf("-- cursor: %s\n", cursor
);
2584 r
= sd_journal_wait(j
, (uint64_t) -1);
2586 log_error_errno(r
, "Couldn't wait for journal event: %m");
2596 strv_free(arg_file
);
2598 strv_free(arg_syslog_identifier
);
2599 strv_free(arg_system_units
);
2600 strv_free(arg_user_units
);
2604 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;