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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2013-06-05 19:30:17 -04:00
parent 5302ebe15f
commit 8d98da3f11
4 changed files with 81 additions and 19 deletions

View file

@ -462,15 +462,29 @@
</varlistentry>
<varlistentry>
<term><option>-D</option></term>
<term><option>--directory=</option></term>
<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 instead of
the default runtime and system journal
paths.</para></listitem>
<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>

View 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) {

View 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) {

View 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);