mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
journalctl: add new --vacuum-size= and --vacuum-time= commands to clean up journal files based on a size/time limit
This is equivalent to the effect of SystemMaxUse= and RetentionSec=, however can be invoked directly instead of implicitly.
This commit is contained in:
@@ -761,8 +761,37 @@
|
||||
<term><option>--disk-usage</option></term>
|
||||
|
||||
<listitem><para>Shows the current disk
|
||||
usage of all
|
||||
journal files.</para></listitem>
|
||||
usage of all journal files. This shows
|
||||
the sum of the disk usage of all
|
||||
archived and active journal
|
||||
files.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--vacuum-size=</option></term>
|
||||
<term><option>--vacuum-time=</option></term>
|
||||
|
||||
<listitem><para>Removes archived
|
||||
journal files until the disk space
|
||||
they use falls below the specified
|
||||
size (specified with the usual K, M,
|
||||
G, T suffixes), or all journal files
|
||||
contain no data older than the
|
||||
specified timespan (specified with the
|
||||
usual s, min, h, days, months, weeks,
|
||||
years suffixes). Note that running
|
||||
<option>--vacuum-size=</option> has
|
||||
only indirect effect on the output
|
||||
shown by <option>--disk-usage</option>
|
||||
as the latter includes active journal
|
||||
files, while the former only operates
|
||||
on archived journal
|
||||
files. <option>--vacuum-size=</option>
|
||||
and <option>--vacuum-time=</option>
|
||||
may be combined in a single invocation
|
||||
to enforce both a size and time limit
|
||||
on the archived journal
|
||||
files.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
||||
@@ -143,7 +143,8 @@ int journal_directory_vacuum(
|
||||
const char *directory,
|
||||
uint64_t max_use,
|
||||
usec_t max_retention_usec,
|
||||
usec_t *oldest_usec) {
|
||||
usec_t *oldest_usec,
|
||||
bool verbose) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r = 0;
|
||||
@@ -152,6 +153,7 @@ int journal_directory_vacuum(
|
||||
size_t n_allocated = 0;
|
||||
uint64_t sum = 0, freed = 0;
|
||||
usec_t retention_limit = 0;
|
||||
char sbytes[FORMAT_BYTES_MAX];
|
||||
|
||||
assert(directory);
|
||||
|
||||
@@ -262,14 +264,12 @@ int journal_directory_vacuum(
|
||||
uint64_t size = 512UL * (uint64_t) st.st_blocks;
|
||||
|
||||
if (unlinkat(dirfd(d), p, 0) >= 0) {
|
||||
log_info("Deleted empty journal %s/%s (%"PRIu64" bytes).",
|
||||
directory, p, size);
|
||||
log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted empty archived journal %s/%s (%s).", directory, p, format_bytes(sbytes, sizeof(sbytes), size));
|
||||
freed += size;
|
||||
} else if (errno != ENOENT)
|
||||
log_warning("Failed to delete %s/%s: %m", directory, p);
|
||||
log_warning("Failed to delete empty archived journal %s/%s: %m", directory, p);
|
||||
|
||||
free(p);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -297,8 +297,7 @@ int journal_directory_vacuum(
|
||||
break;
|
||||
|
||||
if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) {
|
||||
log_debug("Deleted archived journal %s/%s (%"PRIu64" bytes).",
|
||||
directory, list[i].filename, list[i].usage);
|
||||
log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted archived journal %s/%s (%s).", directory, list[i].filename, format_bytes(sbytes, sizeof(sbytes), list[i].usage));
|
||||
freed += list[i].usage;
|
||||
|
||||
if (list[i].usage < sum)
|
||||
@@ -307,7 +306,7 @@ int journal_directory_vacuum(
|
||||
sum = 0;
|
||||
|
||||
} else if (errno != ENOENT)
|
||||
log_warning("Failed to delete %s/%s: %m", directory, list[i].filename);
|
||||
log_warning("Failed to delete archived journal %s/%s: %m", directory, list[i].filename);
|
||||
}
|
||||
|
||||
if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec))
|
||||
@@ -318,7 +317,7 @@ finish:
|
||||
free(list[i].filename);
|
||||
free(list);
|
||||
|
||||
log_debug("Vacuuming done, freed %"PRIu64" bytes", freed);
|
||||
log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -23,4 +23,4 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
int journal_directory_vacuum(const char *directory, uint64_t max_use, usec_t max_retention_usec, usec_t *oldest_usec);
|
||||
int journal_directory_vacuum(const char *directory, uint64_t max_use, usec_t max_retention_usec, usec_t *oldest_usec, bool vacuum);
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "journal-verify.h"
|
||||
#include "journal-authenticate.h"
|
||||
#include "journal-qrcode.h"
|
||||
#include "journal-vacuum.h"
|
||||
#include "fsprg.h"
|
||||
#include "unit-name.h"
|
||||
#include "catalog.h"
|
||||
@@ -111,6 +112,8 @@ static bool arg_reverse = false;
|
||||
static int arg_journal_type = 0;
|
||||
static const char *arg_root = NULL;
|
||||
static const char *arg_machine = NULL;
|
||||
static off_t arg_vacuum_size = (off_t) -1;
|
||||
static usec_t arg_vacuum_time = USEC_INFINITY;
|
||||
|
||||
static enum {
|
||||
ACTION_SHOW,
|
||||
@@ -124,6 +127,7 @@ static enum {
|
||||
ACTION_UPDATE_CATALOG,
|
||||
ACTION_LIST_BOOTS,
|
||||
ACTION_FLUSH,
|
||||
ACTION_VACUUM,
|
||||
} arg_action = ACTION_SHOW;
|
||||
|
||||
typedef struct boot_id_t {
|
||||
@@ -231,14 +235,16 @@ static void help(void) {
|
||||
"\nCommands:\n"
|
||||
" -h --help Show this help text\n"
|
||||
" --version Show package version\n"
|
||||
" --new-id128 Generate a new 128-bit ID\n"
|
||||
" --header Show journal header information\n"
|
||||
" --disk-usage Show total disk usage of all journal files\n"
|
||||
" -F --field=FIELD List all values that a specified field takes\n"
|
||||
" --new-id128 Generate a new 128-bit ID\n"
|
||||
" --disk-usage Show total disk usage of all journal files\n"
|
||||
" --vacuum-size=BYTES Remove old journals until disk space drops below size\n"
|
||||
" --vacuum-time=TIME Remove old journals until none left older than\n"
|
||||
" --flush Flush all journal data from /run into /var\n"
|
||||
" --header Show journal header information\n"
|
||||
" --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"
|
||||
@@ -276,6 +282,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_FORCE,
|
||||
ARG_UTC,
|
||||
ARG_FLUSH,
|
||||
ARG_VACUUM_SIZE,
|
||||
ARG_VACUUM_TIME,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -327,6 +335,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "machine", required_argument, NULL, 'M' },
|
||||
{ "utc", no_argument, NULL, ARG_UTC },
|
||||
{ "flush", no_argument, NULL, ARG_FLUSH },
|
||||
{ "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
|
||||
{ "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -525,6 +535,26 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_action = ACTION_DISK_USAGE;
|
||||
break;
|
||||
|
||||
case ARG_VACUUM_SIZE:
|
||||
r = parse_size(optarg, 1024, &arg_vacuum_size);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse vacuum size: %s", optarg);
|
||||
return r;
|
||||
}
|
||||
|
||||
arg_action = ACTION_VACUUM;
|
||||
break;
|
||||
|
||||
case ARG_VACUUM_TIME:
|
||||
r = parse_sec(optarg, &arg_vacuum_time);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse vacuum time: %s", optarg);
|
||||
return r;
|
||||
}
|
||||
|
||||
arg_action = ACTION_VACUUM;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_GCRYPT
|
||||
case ARG_FORCE:
|
||||
arg_force = true;
|
||||
@@ -1812,11 +1842,31 @@ int main(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
printf("Journals take up %s on disk.\n",
|
||||
printf("Archived and active journals take up %s on disk.\n",
|
||||
format_bytes(sbytes, sizeof(sbytes), bytes));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (arg_action == ACTION_VACUUM) {
|
||||
Directory *d;
|
||||
Iterator i;
|
||||
|
||||
HASHMAP_FOREACH(d, j->directories_by_path, i) {
|
||||
int q;
|
||||
|
||||
if (d->is_root)
|
||||
continue;
|
||||
|
||||
q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_time, NULL, true);
|
||||
if (q < 0) {
|
||||
log_error("Failed to vacuum: %s", strerror(-q));
|
||||
r = q;
|
||||
}
|
||||
}
|
||||
|
||||
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (arg_action == ACTION_LIST_BOOTS) {
|
||||
r = list_boots(j);
|
||||
goto finish;
|
||||
|
||||
@@ -375,7 +375,7 @@ static void do_vacuum(Server *s, char *ids, JournalFile *f, const char* path,
|
||||
return;
|
||||
|
||||
p = strappenda(path, ids);
|
||||
r = journal_directory_vacuum(p, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec);
|
||||
r = journal_directory_vacuum(p, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec, false);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_error("Failed to vacuum %s: %s", p, strerror(-r));
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ static void test_skip(void (*setup)(void)) {
|
||||
if (arg_keep)
|
||||
log_info("Not removing %s", t);
|
||||
else {
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL);
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL, true);
|
||||
|
||||
assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
|
||||
}
|
||||
@@ -274,7 +274,7 @@ static void test_sequence_numbers(void) {
|
||||
if (arg_keep)
|
||||
log_info("Not removing %s", t);
|
||||
else {
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL);
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL, true);
|
||||
|
||||
assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ static void test_non_empty(void) {
|
||||
if (arg_keep)
|
||||
log_info("Not removing %s", t);
|
||||
else {
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL);
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL, true);
|
||||
|
||||
assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
|
||||
}
|
||||
@@ -165,7 +165,7 @@ static void test_empty(void) {
|
||||
if (arg_keep)
|
||||
log_info("Not removing %s", t);
|
||||
else {
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL);
|
||||
journal_directory_vacuum(".", 3000000, 0, NULL, true);
|
||||
|
||||
assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user