chiark / gitweb /
journalctl: allow the user to specify the file(s) to use
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 5 Jun 2013 23:30:17 +0000 (19:30 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 10 Jun 2013 14:10:07 +0000 (10:10 -0400)
This is useful for debugging and feels pretty natural. For example
answering the question "is this big .journal file worth keeping?"
is made easier.

man/journalctl.xml
src/journal/journalctl.c
src/shared/util.c
src/shared/util.h

index 66100816ae4070c4ce7bce35dc60da32ad733fb8..f39986817879b514b198f5230bc19031d70ab8f8 100644 (file)
                         </varlistentry>
 
                         <varlistentry>
-                                <term><option>-D</option></term>
-                                <term><option>--directory=</option></term>
-
-                                <listitem><para>Takes a
-                                directory path as argument. If
-                                specified journalctl will operate on the
-                                specified journal directory instead of
-                                the default runtime and system journal
-                                paths.</para></listitem>
+                                <term><option>-D <replaceable>DIR</replaceable></option></term>
+                                <term><option>--directory=<replaceable>DIR</replaceable></option></term>
+
+                                <listitem><para>Takes a directory path
+                                as argument. If specified journalctl
+                                will operate on the specified journal
+                                directory
+                                <replaceable>DIR</replaceable> instead
+                                of the default runtime and system
+                                journal paths.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--file=<replaceable>GLOB</replaceable></option></term>
+
+                                <listitem><para>Takes a file glob as
+                                argument. If specified journalctl will
+                                operate on the specified journal files
+                                matching <replaceable>GLOB</replaceable>
+                                instead of the default runtime and
+                                system journal paths. May be specified
+                                multiple times, in which case files will
+                                be suitably interleaved.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
index af0f4ba3c8b9f289d0d6a35eb4f61d6ed9b08529..1a441dd0d68c17d934f49634195703eadb756d8b 100644 (file)
@@ -74,6 +74,7 @@ static bool arg_this_boot = false;
 static bool arg_dmesg = false;
 static const char *arg_cursor = NULL;
 static const char *arg_directory = NULL;
+static char **arg_file = NULL;
 static int arg_priorities = 0xFF;
 static const char *arg_verify_key = NULL;
 #ifdef HAVE_GCRYPT
@@ -130,6 +131,7 @@ static int help(void) {
                "     --no-pager          Do not pipe output into a pager\n"
                "  -m --merge             Show entries from all available journals\n"
                "  -D --directory=PATH    Show journal files from directory\n"
+               "     --file=PATH         Show journal file\n"
                "     --root=ROOT         Operate on catalog files underneath the root ROOT\n"
 #ifdef HAVE_GCRYPT
                "     --interval=TIME     Time interval for changing the FSS sealing key\n"
@@ -167,6 +169,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_HEADER,
                 ARG_FULL,
                 ARG_SETUP_KEYS,
+                ARG_FILE,
                 ARG_INTERVAL,
                 ARG_VERIFY,
                 ARG_VERIFY_KEY,
@@ -198,6 +201,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "system",       no_argument,       NULL, ARG_SYSTEM       },
                 { "user",         no_argument,       NULL, ARG_USER         },
                 { "directory",    required_argument, NULL, 'D'              },
+                { "file",         required_argument, NULL, ARG_FILE         },
                 { "root",         required_argument, NULL, ARG_ROOT         },
                 { "header",       no_argument,       NULL, ARG_HEADER       },
                 { "priority",     required_argument, NULL, 'p'              },
@@ -343,6 +347,14 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_directory = optarg;
                         break;
 
+                case ARG_FILE:
+                        r = glob_extend(&arg_file, optarg);
+                        if (r < 0) {
+                                log_error("Failed to add paths: %s", strerror(-r));
+                                return r;
+                        };
+                        break;
+
                 case ARG_ROOT:
                         arg_root = optarg;
                         break;
@@ -506,6 +518,11 @@ static int parse_argv(int argc, char *argv[]) {
         if (arg_follow && !arg_no_tail && arg_lines < 0)
                 arg_lines = 10;
 
+        if (arg_directory && arg_file) {
+                log_error("Please specify either -D/--directory= or --file=, not both.");
+                return -EINVAL;
+        }
+
         if (arg_since_set && arg_until_set && arg_since > arg_until) {
                 log_error("--since= must be before --until=.");
                 return -EINVAL;
@@ -1110,10 +1127,14 @@ int main(int argc, char *argv[]) {
 
         if (arg_directory)
                 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
+        else if (arg_file)
+                r = sd_journal_open_files(&j, (const char**) arg_file, 0);
         else
                 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
         if (r < 0) {
-                log_error("Failed to open journal: %s", strerror(-r));
+                log_error("Failed to open %s: %s",
+                          arg_directory ? arg_directory : arg_file ? "files" : "journal",
+                          strerror(-r));
                 return EXIT_FAILURE;
         }
 
@@ -1167,10 +1188,7 @@ int main(int argc, char *argv[]) {
         if (r < 0)
                 return EXIT_FAILURE;
 
-        /* Opening the fd now means the first sd_journal_wait() will actually wait */
-        r = sd_journal_get_fd(j);
-        if (r < 0)
-                return EXIT_FAILURE;
+        log_debug("Journal filter: %s", j->level0 ? journal_make_match_string(j) : "none");
 
         if (arg_field) {
                 const void *data;
@@ -1206,6 +1224,13 @@ int main(int argc, char *argv[]) {
                 return EXIT_SUCCESS;
         }
 
+        /* Opening the fd now means the first sd_journal_wait() will actually wait */
+        if (arg_follow) {
+                r = sd_journal_get_fd(j);
+                if (r < 0)
+                        return EXIT_FAILURE;
+        }
+
         if (arg_cursor) {
                 r = sd_journal_seek_cursor(j, arg_cursor);
                 if (r < 0) {
index 17928ec36ee287c4f2ffb2e9ef541cc3eeee5cf3..04811ff26b8a64f94d9629e9fc27d1102232a78a 100644 (file)
@@ -4353,7 +4353,7 @@ int in_group(const char *name) {
 
 int glob_exists(const char *path) {
         _cleanup_globfree_ glob_t g = {};
-        int r, k;
+        int k;
 
         assert(path);
 
@@ -4361,15 +4361,37 @@ int glob_exists(const char *path) {
         k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
 
         if (k == GLOB_NOMATCH)
-                r = 0;
+                return 0;
         else if (k == GLOB_NOSPACE)
-                r = -ENOMEM;
+                return -ENOMEM;
         else if (k == 0)
-                r = !strv_isempty(g.gl_pathv);
+                return !strv_isempty(g.gl_pathv);
         else
-                r = errno ? -errno : -EIO;
+                return errno ? -errno : -EIO;
+}
 
-        return r;
+int glob_extend(char ***strv, const char *path) {
+        _cleanup_globfree_ glob_t g = {};
+        int k;
+        char **p;
+
+        errno = 0;
+        k = glob(optarg, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+        if (k == GLOB_NOMATCH)
+                return -ENOENT;
+        else if (k == GLOB_NOSPACE)
+                return -ENOMEM;
+        else if (k != 0 || strv_isempty(g.gl_pathv))
+                return errno ? -errno : -EIO;
+
+        STRV_FOREACH(p, g.gl_pathv) {
+                k = strv_extend(strv, *p);
+                if (k < 0)
+                        break;
+        }
+
+        return k;
 }
 
 int dirent_ensure_type(DIR *d, struct dirent *de) {
index e6f9312e9513738ef0ae731b8bcca7a6fc978f0c..ddb21b4a9c596b52edf3dc0ea41e70cc0a791c33 100644 (file)
@@ -439,6 +439,7 @@ char* uid_to_name(uid_t uid);
 char* gid_to_name(gid_t gid);
 
 int glob_exists(const char *path);
+int glob_extend(char ***strv, const char *path);
 
 int dirent_ensure_type(DIR *d, struct dirent *de);