From: Zbigniew Jędrzejewski-Szmek Date: Wed, 5 Jun 2013 23:30:17 +0000 (-0400) Subject: journalctl: allow the user to specify the file(s) to use X-Git-Tag: v205~140 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=8d98da3f1107529d5ba49aea1fa285f7264b7cba journalctl: allow the user to specify the file(s) to use This is useful for debugging and feels pretty natural. For example answering the question "is this big .journal file worth keeping?" is made easier. --- diff --git a/man/journalctl.xml b/man/journalctl.xml index 66100816a..f39986817 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -462,15 +462,29 @@ - - - - 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. + + + + Takes a directory path + as argument. If specified journalctl + will operate on the specified journal + directory + DIR instead + of the default runtime and system + journal paths. + + + + + + Takes a file glob as + argument. If specified journalctl will + operate on the specified journal files + matching GLOB + instead of the default runtime and + system journal paths. May be specified + multiple times, in which case files will + be suitably interleaved. diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index af0f4ba3c..1a441dd0d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -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) { diff --git a/src/shared/util.c b/src/shared/util.c index 17928ec36..04811ff26 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -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) { diff --git a/src/shared/util.h b/src/shared/util.h index e6f9312e9..ddb21b4a9 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -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);