From: Lennart Poettering Date: Mon, 3 Nov 2014 22:08:33 +0000 (+0100) Subject: journalctl: add new --vacuum-size= and --vacuum-time= commands to clean up journal... X-Git-Tag: v218~589 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=dbd2a83fbf051fc51bdca3aa7536c78479488c5b 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. --- diff --git a/man/journalctl.xml b/man/journalctl.xml index 0ed3ca3bc..0703bf9fb 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -761,8 +761,37 @@ Shows the current disk - usage of all - journal files. + usage of all journal files. This shows + the sum of the disk usage of all + archived and active journal + files. + + + + + + + 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 + has + only indirect effect on the output + shown by + as the latter includes active journal + files, while the former only operates + on archived journal + files. + and + may be combined in a single invocation + to enforce both a size and time limit + on the archived journal + files. diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c index 7699482a7..dbf5d2261 100644 --- a/src/journal/journal-vacuum.c +++ b/src/journal/journal-vacuum.c @@ -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; } diff --git a/src/journal/journal-vacuum.h b/src/journal/journal-vacuum.h index bc30c3a14..a7fb6f0f0 100644 --- a/src/journal/journal-vacuum.h +++ b/src/journal/journal-vacuum.h @@ -23,4 +23,4 @@ #include -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); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f50faf42a..b168d1e5f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -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" + " -F --field=FIELD List all values that a specified field takes\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" + " --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; diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index cf6bbcc1a..19cd6fe77 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -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)); } diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 6c5995e0c..8067cd38e 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -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); } diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 6025d04ba..74168b9b8 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -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); }