chiark / gitweb /
journalctl: add new --vacuum-size= and --vacuum-time= commands to clean up journal...
authorLennart Poettering <lennart@poettering.net>
Mon, 3 Nov 2014 22:08:33 +0000 (23:08 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 3 Nov 2014 22:08:33 +0000 (23:08 +0100)
This is equivalent to the effect of SystemMaxUse= and RetentionSec=,
however can be invoked directly instead of implicitly.

man/journalctl.xml
src/journal/journal-vacuum.c
src/journal/journal-vacuum.h
src/journal/journalctl.c
src/journal/journald-server.c
src/journal/test-journal-interleaving.c
src/journal/test-journal.c

index 0ed3ca3bc8750b23930ba12575a48d031a9d685d..0703bf9fb613f45c58370174b1beab5f4c104aca 100644 (file)
                                 <term><option>--disk-usage</option></term>
 
                                 <listitem><para>Shows the current disk
                                 <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>
                         </varlistentry>
 
                         <varlistentry>
index 7699482a7756c13f69769bae2aea664159781c82..dbf5d2261b9975da8910a05b9cad5fccaa376a3e 100644 (file)
@@ -143,7 +143,8 @@ int journal_directory_vacuum(
                 const char *directory,
                 uint64_t max_use,
                 usec_t max_retention_usec,
                 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;
 
         _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;
         size_t n_allocated = 0;
         uint64_t sum = 0, freed = 0;
         usec_t retention_limit = 0;
+        char sbytes[FORMAT_BYTES_MAX];
 
         assert(directory);
 
 
         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) {
                         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)
                                 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);
 
                         free(p);
-
                         continue;
                 }
 
                         continue;
                 }
 
@@ -297,8 +297,7 @@ int journal_directory_vacuum(
                         break;
 
                 if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) {
                         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)
                         freed += list[i].usage;
 
                         if (list[i].usage < sum)
@@ -307,7 +306,7 @@ int journal_directory_vacuum(
                                 sum = 0;
 
                 } else if (errno != ENOENT)
                                 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))
         }
 
         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);
 
                 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;
 }
 
         return r;
 }
index bc30c3a1408e4edcb799286a76ce3e3f4c03d063..a7fb6f0f0d6a8f0aa3bd58c8e27423f8c09674e4 100644 (file)
@@ -23,4 +23,4 @@
 
 #include <inttypes.h>
 
 
 #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);
index f50faf42adf180e1e35fa67d68daa62787bb789a..b168d1e5f69a0ad93a97b83a2c7ae96d7455a9c9 100644 (file)
@@ -59,6 +59,7 @@
 #include "journal-verify.h"
 #include "journal-authenticate.h"
 #include "journal-qrcode.h"
 #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"
 #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 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,
 
 static enum {
         ACTION_SHOW,
@@ -124,6 +127,7 @@ static enum {
         ACTION_UPDATE_CATALOG,
         ACTION_LIST_BOOTS,
         ACTION_FLUSH,
         ACTION_UPDATE_CATALOG,
         ACTION_LIST_BOOTS,
         ACTION_FLUSH,
+        ACTION_VACUUM,
 } arg_action = ACTION_SHOW;
 
 typedef struct boot_id_t {
 } 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"
                "\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"
                "     --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"
                "     --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"
                "     --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"
 #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_FORCE,
                 ARG_UTC,
                 ARG_FLUSH,
+                ARG_VACUUM_SIZE,
+                ARG_VACUUM_TIME,
         };
 
         static const struct option options[] = {
         };
 
         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          },
                 { "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;
 
                         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;
 #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;
 
                 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;
         }
 
                        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;
         if (arg_action == ACTION_LIST_BOOTS) {
                 r = list_boots(j);
                 goto finish;
index cf6bbcc1a851434214252936fd40ecd35ab279ce..19cd6fe77c2a2cd94967dc21393cdc6a158c2417 100644 (file)
@@ -375,7 +375,7 @@ static void do_vacuum(Server *s, char *ids, JournalFile *f, const char* path,
                 return;
 
         p = strappenda(path, ids);
                 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));
 }
         if (r < 0 && r != -ENOENT)
                 log_error("Failed to vacuum %s: %s", p, strerror(-r));
 }
index 6c5995e0c14a5355fa79e7a879222a1173c67438..8067cd38ee3bf22240b36c0cd5df0b9350ad5d0a 100644 (file)
@@ -189,7 +189,7 @@ static void test_skip(void (*setup)(void)) {
         if (arg_keep)
                 log_info("Not removing %s", t);
         else {
         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);
         }
 
                 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 {
         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);
         }
 
                 assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
         }
index 6025d04ba4c18a7d53037824ec839b91c28a3aef..74168b9b830e2e2dd84e4e347ebdb07439252590 100644 (file)
@@ -126,7 +126,7 @@ static void test_non_empty(void) {
         if (arg_keep)
                 log_info("Not removing %s", t);
         else {
         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);
         }
 
                 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 {
         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);
         }
 
                 assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
         }