mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
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.
This commit is contained in:
parent
0e2f14014c
commit
74055aa762
@ -878,6 +878,20 @@
|
||||
operation.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--flush</option></term>
|
||||
|
||||
<listitem><para>Asks the Journal
|
||||
daemon to flush any log data stored in
|
||||
<filename>/run/systemd/log</filename>
|
||||
into
|
||||
<filename>/var/systemd/log</filename>,
|
||||
if persistent storage is enabled. This
|
||||
call does not return until the
|
||||
operation is
|
||||
complete.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,9 @@ Documentation=man:systemd-journald.service(8) man:journald.conf(5)
|
||||
DefaultDependencies=no
|
||||
Requires=systemd-journald.service
|
||||
After=systemd-journald.service local-fs.target remote-fs.target
|
||||
Before=systemd-user-sessions.service
|
||||
Before=systemd-user-sessions.service systemd-tmpfiles-setup.service
|
||||
|
||||
[Service]
|
||||
ExecStart=@rootbindir@/systemctl kill --kill-who=main --signal=SIGUSR1 systemd-journald.service
|
||||
ExecStart=@rootbindir@/journalctl --flush
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
|
Loading…
Reference in New Issue
Block a user