summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2013-06-05 19:30:17 -0400
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2013-06-10 10:10:07 -0400
commit8d98da3f1107529d5ba49aea1fa285f7264b7cba (patch)
tree2382b9eb2cd9c111b227fa5a8f809ad0f7c47586
parent5302ebe15ff3a11eceb75e095e5a09d2a676de2b (diff)
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.
-rw-r--r--man/journalctl.xml32
-rw-r--r--src/journal/journalctl.c35
-rw-r--r--src/shared/util.c34
-rw-r--r--src/shared/util.h1
4 files changed, 82 insertions, 20 deletions
diff --git a/man/journalctl.xml b/man/journalctl.xml
index 66100816ae..f399868178 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -462,15 +462,29 @@
</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>
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index af0f4ba3c8..1a441dd0d6 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 17928ec36e..04811ff26b 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 e6f9312e95..ddb21b4a9c 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);