summaryrefslogtreecommitdiff
path: root/src/journal
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-12-11 22:04:03 +0100
committerLennart Poettering <lennart@poettering.net>2013-12-11 22:04:03 +0100
commitb6741478e7661c7e580e5dcfd6a6fccd1899c1d0 (patch)
treeb29e463c8113c914a21b45226a845424214ece21 /src/journal
parent842129f58752864d4433792c9c47d40508c4439a (diff)
journal: add ability to browse journals of running OS containers
This adds the new library call sd_journal_open_container() and a new "-M" switch to journalctl. Particular care is taken that journalctl's "-b" switch resolves to the current boot ID of the container, not the host.
Diffstat (limited to 'src/journal')
-rw-r--r--src/journal/journalctl.c17
-rw-r--r--src/journal/libsystemd-journal.sym5
-rw-r--r--src/journal/sd-journal.c66
3 files changed, 70 insertions, 18 deletions
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index f74dde9c48..5d12c2b162 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -93,6 +93,7 @@ static bool arg_catalog = false;
static bool arg_reverse = false;
static int arg_journal_type = 0;
static const char *arg_root = NULL;
+static const char *arg_machine = NULL;
static enum {
ACTION_SHOW,
@@ -120,6 +121,7 @@ static int help(void) {
"Flags:\n"
" --system Show only the system journal\n"
" --user Show only the user journal for current user\n"
+ " -M --machine=CONTAINER Operate on local container\n"
" --since=DATE Start showing entries newer or of the specified date\n"
" --until=DATE Stop showing entries older or of the specified date\n"
" -c --cursor=CURSOR Start showing entries from specified cursor\n"
@@ -247,6 +249,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
{ "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
{ "reverse", no_argument, NULL, 'r' },
+ { "machine", required_argument, NULL, 'M' },
{}
};
@@ -255,7 +258,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xr", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xrM:", options, NULL)) >= 0) {
switch (c) {
@@ -389,6 +392,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_journal_type |= SD_JOURNAL_CURRENT_USER;
break;
+ case 'M':
+ arg_machine = optarg;
+ break;
+
case 'D':
arg_directory = optarg;
break;
@@ -576,8 +583,8 @@ 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.");
+ if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
+ log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
return -EINVAL;
}
@@ -881,7 +888,7 @@ static int add_boot(sd_journal *j) {
return 0;
if (!arg_boot_descriptor)
- return add_match_this_boot(j);
+ return add_match_this_boot(j, arg_machine);
if (strlen(arg_boot_descriptor) >= 32) {
char tmp = arg_boot_descriptor[32];
@@ -1460,6 +1467,8 @@ int main(int argc, char *argv[]) {
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 if (arg_machine)
+ r = sd_journal_open_container(&j, arg_machine, 0);
else
r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
if (r < 0) {
diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym
index 4eb15910d2..7f10f633f6 100644
--- a/src/journal/libsystemd-journal.sym
+++ b/src/journal/libsystemd-journal.sym
@@ -109,3 +109,8 @@ LIBSYSTEMD_JOURNAL_205 {
global:
sd_journal_open_files;
} LIBSYSTEMD_JOURNAL_202;
+
+LIBSYSTEMD_JOURNAL_209 {
+global:
+ sd_journal_open_container;
+} LIBSYSTEMD_JOURNAL_205;
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 2ba7ca4559..b55cf37e50 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -41,6 +41,7 @@
#include "missing.h"
#include "catalog.h"
#include "replace-var.h"
+#include "fileio.h"
#define JOURNAL_FILES_MAX 1024
@@ -1465,7 +1466,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
return 0;
}
-static int add_root_directory(sd_journal *j, const char *p) {
+static int add_root_directory(sd_journal *j, const char *p, const char *prefix) {
_cleanup_closedir_ DIR *d = NULL;
Directory *m;
int r;
@@ -1477,6 +1478,9 @@ static int add_root_directory(sd_journal *j, const char *p) {
!path_startswith(p, "/run"))
return -EINVAL;
+ if (prefix)
+ p = strappenda(prefix, p);
+
d = opendir(p);
if (!d)
return -errno;
@@ -1576,7 +1580,7 @@ static int remove_directory(sd_journal *j, Directory *d) {
return 0;
}
-static int add_search_paths(sd_journal *j) {
+static int add_search_paths(sd_journal *j, const char *prefix) {
int r;
const char search_paths[] =
"/run/log/journal\0"
@@ -1589,7 +1593,7 @@ static int add_search_paths(sd_journal *j) {
* what's actually accessible, and ignore the rest. */
NULSTR_FOREACH(p, search_paths) {
- r = add_root_directory(j, p);
+ r = add_root_directory(j, p, prefix);
if (r < 0 && r != -ENOENT) {
r = set_put_error(j, r);
if (r < 0)
@@ -1619,7 +1623,7 @@ static int add_current_paths(sd_journal *j) {
if (!dir)
return -ENOMEM;
- r = add_root_directory(j, dir);
+ r = add_root_directory(j, dir, NULL);
if (r < 0) {
set_put_error(j, r);
return r;
@@ -1684,18 +1688,13 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
int r;
assert_return(ret, -EINVAL);
-
- if (flags & ~(SD_JOURNAL_LOCAL_ONLY|
- SD_JOURNAL_RUNTIME_ONLY|
- SD_JOURNAL_SYSTEM|
- SD_JOURNAL_CURRENT_USER))
- return -EINVAL;
+ assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL);
j = journal_new(flags, NULL);
if (!j)
return -ENOMEM;
- r = add_search_paths(j);
+ r = add_search_paths(j, NULL);
if (r < 0)
goto fail;
@@ -1708,6 +1707,45 @@ fail:
return r;
}
+_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
+ _cleanup_free_ char *root = NULL, *class = NULL;
+ sd_journal *j;
+ char *p;
+ int r;
+
+ assert_return(machine, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
+ assert_return(filename_is_safe(machine), -EINVAL);
+
+ p = strappenda("/run/systemd/machines/", machine);
+ r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
+ if (r == -ENOENT)
+ return -EHOSTDOWN;
+ if (r < 0)
+ return r;
+ if (!root)
+ return -ENODATA;
+
+ if (!streq_ptr(class, "container"))
+ return -EIO;
+
+ j = journal_new(flags, NULL);
+ if (!j)
+ return -ENOMEM;
+
+ r = add_search_paths(j, root);
+ if (r < 0)
+ goto fail;
+
+ *ret = j;
+ return 0;
+
+fail:
+ sd_journal_close(j);
+ return r;
+}
+
_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
sd_journal *j;
int r;
@@ -1720,7 +1758,7 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
if (!j)
return -ENOMEM;
- r = add_root_directory(j, path);
+ r = add_root_directory(j, path, NULL);
if (r < 0) {
set_put_error(j, r);
goto fail;
@@ -2083,9 +2121,9 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
if (j->no_new_files)
r = add_current_paths(j);
else if (j->path)
- r = add_root_directory(j, j->path);
+ r = add_root_directory(j, j->path, NULL);
else
- r = add_search_paths(j);
+ r = add_search_paths(j, NULL);
if (r < 0)
return r;