diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-10-23 00:28:17 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-10-23 00:39:42 +0200 |
commit | 74055aa76278232ff05574fc47c4e6b3560554a7 (patch) | |
tree | cebf74b2f97108dc325ce4522962863b2b4c2f35 /src/journal | |
parent | 0e2f14014c65b4d8b30146e414579154cfa932da (diff) |
journalctl: add new --flush command and make use of it in systemd-journal-flush.service
This new command will ask the journal daemon to flush all log data
stored in /run to /var, and wait for it to complete. This is useful, so
that in case of Storage=persistent we can order systemd-tmpfiles-setup
afterwards, to ensure any possibly newly created directory in /var/log
gets proper access mode and owners.
Diffstat (limited to 'src/journal')
-rw-r--r-- | src/journal/journalctl.c | 92 | ||||
-rw-r--r-- | src/journal/journald-server.c | 3 |
2 files changed, 93 insertions, 2 deletions
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ee4e1659b0..c32028268a 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -31,8 +31,10 @@ #include <time.h> #include <getopt.h> #include <signal.h> +#include <poll.h> #include <sys/stat.h> #include <sys/ioctl.h> +#include <sys/inotify.h> #include <linux/fs.h> #ifdef HAVE_ACL @@ -40,7 +42,8 @@ #include "acl-util.h" #endif -#include "systemd/sd-journal.h" +#include "sd-journal.h" +#include "sd-bus.h" #include "log.h" #include "logs-show.h" @@ -59,6 +62,9 @@ #include "fsprg.h" #include "unit-name.h" #include "catalog.h" +#include "mkdir.h" +#include "bus-util.h" +#include "bus-error.h" #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) @@ -117,6 +123,7 @@ static enum { ACTION_DUMP_CATALOG, ACTION_UPDATE_CATALOG, ACTION_LIST_BOOTS, + ACTION_FLUSH, } arg_action = ACTION_SHOW; typedef struct boot_id_t { @@ -231,6 +238,7 @@ static void help(void) { " --list-catalog Show message IDs of all entries in the message catalog\n" " --dump-catalog Show entries in the message catalog\n" " --update-catalog Update the message catalog database\n" + " --flush Flush all journal data from /run into /var\n" #ifdef HAVE_GCRYPT " --setup-keys Generate a new FSS key pair\n" " --verify Verify journal file consistency\n" @@ -267,6 +275,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_UPDATE_CATALOG, ARG_FORCE, ARG_UTC, + ARG_FLUSH, }; static const struct option options[] = { @@ -317,6 +326,7 @@ static int parse_argv(int argc, char *argv[]) { { "reverse", no_argument, NULL, 'r' }, { "machine", required_argument, NULL, 'M' }, { "utc", no_argument, NULL, ARG_UTC }, + { "flush", no_argument, NULL, ARG_FLUSH }, {} }; @@ -661,6 +671,10 @@ static int parse_argv(int argc, char *argv[]) { arg_utc = true; break; + case ARG_FLUSH: + arg_action = ACTION_FLUSH; + break; + case '?': return -EINVAL; @@ -1641,6 +1655,77 @@ static int access_check(sd_journal *j) { return r; } +static int flush_to_var(void) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_close_ int watch_fd = -1; + int r; + + /* Quick exit */ + if (access("/run/systemd/journal/flushed", F_OK) >= 0) + return 0; + + /* OK, let's actually do the full logic, send SIGUSR1 to the + * daemon and set up inotify to wait for the flushed file to appear */ + r = bus_open_system_systemd(&bus); + if (r < 0) { + log_error("Failed to get D-Bus connection: %s", strerror(-r)); + return r; + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "KillUnit", + &error, + NULL, + "ssi", "systemd-journald.service", "main", SIGUSR1); + if (r < 0) { + log_error("Failed to kill journal service: %s", bus_error_message(&error, r)); + return r; + } + + mkdir_p("/run/systemd/journal", 0755); + + watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (watch_fd < 0) { + log_error("Failed to create inotify watch: %m"); + return -errno; + } + + r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR); + if (r < 0) { + log_error("Failed to watch journal directory: %m"); + return -errno; + } + + for (;;) { + if (access("/run/systemd/journal/flushed", F_OK) >= 0) + break; + + if (errno != ENOENT) { + log_error("Failed to check for existance of /run/systemd/journal/flushed: %m"); + return -errno; + } + + r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY); + if (r < 0) { + log_error("Failed to wait for event: %s", strerror(-r)); + return r; + } + + r = flush_fd(watch_fd); + if (r < 0) { + log_error("Failed to flush inotify events: %s", strerror(-r)); + return r; + } + } + + return 0; +} + int main(int argc, char *argv[]) { int r; _cleanup_journal_close_ sd_journal *j = NULL; @@ -1665,6 +1750,11 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_action == ACTION_FLUSH) { + r = flush_to_var(); + goto finish; + } + if (arg_action == ACTION_SETUP_KEYS) { r = setup_keys(); goto finish; diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index bf9cfcccc9..991f4f2a38 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1221,11 +1221,12 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo * log_info("Received request to flush runtime journal from PID %"PRIu32, si->ssi_pid); - touch("/run/systemd/journal/flushed"); server_flush_to_var(s); server_sync(s); server_vacuum(s); + touch("/run/systemd/journal/flushed"); + return 0; } |