summaryrefslogtreecommitdiff
path: root/src/journal/journalctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/journal/journalctl.c')
-rw-r--r--src/journal/journalctl.c92
1 files changed, 91 insertions, 1 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;