journalctl.c revision a54e3b3d6a4fe28a39729f4c5ad11cd26706110c
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen This file is part of systemd.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen Copyright 2011 Lennart Poettering
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen systemd is free software; you can redistribute it and/or modify it
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen under the terms of the GNU Lesser General Public License as published by
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen (at your option) any later version.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen systemd is distributed in the hope that it will be useful, but
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen Lesser General Public License for more details.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen You should have received a copy of the GNU Lesser General Public License
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_pager_end = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_follow = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_full = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_all = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_no_pager = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_no_tail = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_quiet = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_merge = false;
02b59d57e0c08231645120077f651151f5bb2babTom Gundersenstatic bool arg_boot = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic bool arg_dmesg = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic bool arg_show_cursor = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic bool arg_force = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic bool arg_since_set = false, arg_until_set = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic bool arg_catalog = false;
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersenstatic bool arg_reverse = false;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersentypedef struct boot_id_t {
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersenstatic int help(void) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen "Query the journal.\n\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " --system Show only the system journal\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --user Show only the user journal for current user\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --since=DATE Start showing entries newer or of the specified date\n"
b3070dc0258831c7e2b13624f75fa3dbd80d9833Tom Gundersen " --until=DATE Stop showing entries older or of the specified date\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " -c --cursor=CURSOR Start showing entries from specified cursor\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --after-cursor=CURSOR Start showing entries from specified cursor\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --show-cursor Print the cursor after all the entries\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " -b --boot[=ID] Show data only from ID or current boot if unspecified\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " -k --dmesg Show kernel message log from current boot\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " -u --unit=UNIT Show data only from the specified unit\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --user-unit=UNIT Show data only from the specified user session unit\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " -p --priority=RANGE Show only messages within the specified priority range\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " -e --pager-end Immediately jump to end of the journal in the pager\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " -f --follow Follow journal\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " -n --lines[=INTEGER] Number of journal entries to show\n"
6ae115c1fe95611b39d2f20cfcea3d385429f59eTom Gundersen " --no-tail Show all lines, even in follow mode\n"
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen " -r --reverse Show the newest entries first\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " verbose, export, json, json-pretty, json-sse, cat)\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " -x --catalog Add message explanations where available\n"
ef1ba6065c6ccea94d4ee867f36df7bbc53a5224Tom Gundersen " -l --full Do not ellipsize fields\n"
ef1ba6065c6ccea94d4ee867f36df7bbc53a5224Tom Gundersen " -a --all Show all fields, including long and unprintable\n"
ef1ba6065c6ccea94d4ee867f36df7bbc53a5224Tom Gundersen " -q --quiet Don't show privilege warning\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " --no-pager Do not pipe output into a pager\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " -m --merge Show entries from all available journals\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " -D --directory=PATH Show journal files from directory\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " --file=PATH Show journal file\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " --root=ROOT Operate on catalog files underneath the root ROOT\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --interval=TIME Time interval for changing the FSS sealing key\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --verify-key=KEY Specify FSS verification key\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --force Force overriding new FSS key pair with --setup-keys\n"
c166a070553511e402de5ad216d3fb62b49bdacbTom Gundersen "\nCommands:\n"
8cd11a0f0f4ca05199e1166f6a07472b296f7455Tom Gundersen " -h --help Show this help\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --version Show package version\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --new-id128 Generate a new 128 Bit ID\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --header Show journal header information\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen " --disk-usage Show total disk usage\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " -F --field=FIELD List all values a certain field takes\n"
f5be560181d092c5f52a2b819aedcd48220f36abTom Gundersen " --list-catalog Show message IDs of all entries in the message catalog\n"
f5be560181d092c5f52a2b819aedcd48220f36abTom Gundersen " --dump-catalog Show entries in the message catalog\n"
3bef724f7e7f7eaca69881548b06e221b77d7031Tom Gundersen " --update-catalog Update the message catalog database\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " --setup-keys Generate new FSS key pair\n"
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen " --verify Verify journal file consistency\n"
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic int parse_argv(int argc, char *argv[]) {
3bef724f7e7f7eaca69881548b06e221b77d7031Tom Gundersen { "version" , no_argument, NULL, ARG_VERSION },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "no-pager", no_argument, NULL, ARG_NO_PAGER },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "no-tail", no_argument, NULL, ARG_NO_TAIL },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "directory", required_argument, NULL, 'D' },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "file", required_argument, NULL, ARG_FILE },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "root", required_argument, NULL, ARG_ROOT },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "interval", required_argument, NULL, ARG_INTERVAL },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "since", required_argument, NULL, ARG_SINCE },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "until", required_argument, NULL, ARG_UNTIL },
02b59d57e0c08231645120077f651151f5bb2babTom Gundersen { "user-unit", required_argument, NULL, ARG_USER_UNIT },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
f048a16b464295a4e0a4f4c1210f06343ad31231Tom Gundersen { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xr", options, NULL)) >= 0) {
f882c247ad59776c3a7753bb963c1f8e2386cb79Tom Gundersen log_error("Unknown output format '%s'.", optarg);
3333d748facc15f49935b6b793490ba0824976e6Zbigniew Jędrzejewski-Szmek arg_output == OUTPUT_JSON_PRETTY ||
3333d748facc15f49935b6b793490ba0824976e6Zbigniew Jędrzejewski-Szmek arg_output == OUTPUT_JSON_SSE ||
39032b87779323a244dd89f4832949d462b2ac68Zbigniew Jędrzejewski-Szmek r = safe_atoi(optarg, &arg_lines);
39032b87779323a244dd89f4832949d462b2ac68Zbigniew Jędrzejewski-Szmek if (r < 0 || arg_lines < 0) {
39032b87779323a244dd89f4832949d462b2ac68Zbigniew Jędrzejewski-Szmek log_error("Failed to parse lines '%s'", optarg);
628706137efbca8aaf753ccd063e5abf7e31aed5Zbigniew Jędrzejewski-Szmek /* Hmm, no argument? Maybe the next
628706137efbca8aaf753ccd063e5abf7e31aed5Zbigniew Jędrzejewski-Szmek * word on the command line is
628706137efbca8aaf753ccd063e5abf7e31aed5Zbigniew Jędrzejewski-Szmek * supposed to be the argument? Let's
628706137efbca8aaf753ccd063e5abf7e31aed5Zbigniew Jędrzejewski-Szmek * see if there is one, and is
arg_lines = n;
optind++;
case ARG_NO_TAIL:
arg_no_tail = true;
case ARG_NEW_ID128:
arg_quiet = true;
arg_merge = true;
arg_boot = true;
if (optarg)
int boot;
optind++;
case ARG_SYSTEM:
case ARG_USER:
case ARG_FILE:
case ARG_ROOT:
case ARG_AFTER_CURSOR:
case ARG_SHOW_CURSOR:
arg_show_cursor = true;
case ARG_HEADER:
case ARG_VERIFY:
case ARG_DISK_USAGE:
#ifdef HAVE_GCRYPT
case ARG_FORCE:
arg_force = true;
case ARG_SETUP_KEYS:
case ARG_VERIFY_KEY:
arg_merge = false;
case ARG_INTERVAL:
if (r < 0 || arg_interval <= 0) {
return -EINVAL;
case ARG_SETUP_KEYS:
case ARG_VERIFY_KEY:
case ARG_INTERVAL:
case ARG_FORCE:
return -ENOTSUP;
const char *dots;
if (dots) {
return log_oom();
free(a);
return -EINVAL;
arg_priorities = 0;
return -EINVAL;
arg_priorities = 0;
case ARG_SINCE:
return -EINVAL;
arg_since_set = true;
case ARG_UNTIL:
return -EINVAL;
arg_until_set = true;
return log_oom();
case ARG_USER_UNIT:
return log_oom();
return -EINVAL;
arg_catalog = true;
case ARG_LIST_CATALOG:
case ARG_DUMP_CATALOG:
case ARG_UPDATE_CATALOG:
arg_reverse = true;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
static int generate_new_id128(void) {
assert(j);
r = sd_journal_add_disjunction(j);
else if (path_is_absolute(*i)) {
const char *path;
p = canonicalize_file_name(*i);
path = p ? p : *i;
return -errno;
return -EINVAL;
return log_oom();
r = sd_journal_add_match(j, t, 0);
r = sd_journal_add_match(j, *i, 0);
static int boot_id_cmp(const void *a, const void *b) {
const void *data;
unsigned int count = 0;
assert(j);
return log_oom();
r = sd_journal_seek_head(j);
r = sd_journal_next(j);
goto flush;
count++;
return -EADDRNOTAVAIL;
if (!id ||
return -EADDRNOTAVAIL;
char *offset;
int r, relative = 0;
assert(j);
if (!arg_boot)
if (!arg_boot_descriptor)
return add_match_this_boot(j);
return -EINVAL;
if (*offset) {
return -EINVAL;
r = sd_journal_add_conjunction(j);
assert(j);
if (!arg_dmesg)
r = sd_journal_add_conjunction(j);
assert(j);
u = unit_name_mangle(*i);
return log_oom();
r = add_matches_for_unit(j, u);
r = sd_journal_add_disjunction(j);
u = unit_name_mangle(*i);
return log_oom();
r = sd_journal_add_disjunction(j);
r = sd_journal_add_conjunction(j);
assert(j);
r = sd_journal_add_conjunction(j);
static int setup_keys(void) {
#ifdef HAVE_GCRYPT
ssize_t l;
struct FSSHeader h;
uint64_t n;
return -errno;
return log_oom();
if (arg_force) {
r = unlink(p);
r = -errno;
goto finish;
r = -EEXIST;
goto finish;
r = log_oom();
goto finish;
if (fd < 0) {
r = -errno;
goto finish;
r = -EIO;
goto finish;
n /= arg_interval;
if (fd < 0) {
r = -errno;
goto finish;
zero(h);
if (l < 0 || (size_t) l != sizeof(h)) {
r = -EIO;
goto finish;
r = -EIO;
goto finish;
if (link(k, p) < 0) {
r = -errno;
goto finish;
if (on_tty()) {
"The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
"Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
for (i = 0; i < seed_size; i++) {
if (on_tty()) {
if (hn) {
fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
#ifdef HAVE_QRENCODE
if (is_locale_utf8()) {
fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
if (fd >= 0)
unlink(k);
free(k);
free(p);
return -ENOTSUP;
Iterator i;
JournalFile *f;
assert(j);
log_show_color(true);
#ifdef HAVE_GCRYPT
log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
if (k == -EINVAL) {
if (validated > 0) {
} else if (last > 0)
#ifdef HAVE_ACL
bool have_access;
assert(j);
if (!have_access) {
if (!have_access) {
if (strv_isempty(g))
return log_oom();
strv_sort(g);
strv_uniq(g);
return log_oom();
void *code;
assert(j);
#ifdef HAVE_ACL
geteuid() != 0 &&
return -EACCES;
r = access_check_var_log_journal(j);
return -EACCES;
r = -EACCES;
int err;
bool need_seek = false;
int n_shown = 0;
log_open();
goto finish;
r = generate_new_id128();
goto finish;
r = setup_keys();
goto finish;
if (arg_root) {
if (!copy) {
r = log_oom();
goto finish;
goto finish;
if (arg_directory)
else if (arg_file)
strerror(-r));
return EXIT_FAILURE;
r = access_check(j);
return EXIT_FAILURE;
r = verify(j);
goto finish;
return EXIT_SUCCESS;
return EXIT_FAILURE;
return EXIT_SUCCESS;
r = add_boot(j);
return EXIT_FAILURE;
r = add_dmesg(j);
return EXIT_FAILURE;
r = add_units(j);
return EXIT_FAILURE;
r = add_priorities(j);
return EXIT_FAILURE;
return EXIT_FAILURE;
if (arg_field) {
const void *data;
r = sd_journal_set_data_threshold(j, 0);
return EXIT_FAILURE;
return EXIT_FAILURE;
const void *eq;
if (eq)
printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
n_shown ++;
return EXIT_SUCCESS;
if (arg_follow) {
r = sd_journal_get_fd(j);
return EXIT_FAILURE;
return EXIT_FAILURE;
if (!arg_reverse)
arg_lines = 0;
return EXIT_FAILURE;
r = sd_journal_next(j);
return EXIT_FAILURE;
r = sd_journal_previous(j);
} else if (arg_lines >= 0) {
r = sd_journal_seek_tail(j);
return EXIT_FAILURE;
} else if (arg_reverse) {
r = sd_journal_seek_tail(j);
return EXIT_FAILURE;
r = sd_journal_previous(j);
r = sd_journal_seek_head(j);
return EXIT_FAILURE;
r = sd_journal_next(j);
return EXIT_FAILURE;
if (!arg_quiet) {
goto finish;
if (arg_follow)
int flags;
if (need_seek) {
if (!arg_reverse)
r = sd_journal_next(j);
r = sd_journal_previous(j);
goto finish;
goto finish;
goto finish;
goto finish;
goto finish;
if (!arg_merge) {
if (previous_boot_id_valid &&
previous_boot_id_valid = true;
flags =
need_seek = true;
if (r == -EADDRNOTAVAIL)
goto finish;
n_shown++;
if (!arg_follow) {
if (arg_show_cursor) {
if (r < 0 && r != -EADDRNOTAVAIL)
goto finish;
first_line = false;
pager_close();