]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journalctl: implement --list-namespaces
authorFrantisek Sumsal <frantisek@sumsal.cz>
Fri, 5 Jan 2024 17:06:08 +0000 (18:06 +0100)
committerFrantisek Sumsal <frantisek@sumsal.cz>
Fri, 5 Jan 2024 18:21:51 +0000 (19:21 +0100)
Apart from being useful on its own, this will be used in the following
commit for shell completions.

shell-completion/bash/journalctl
shell-completion/zsh/_journalctl
src/journal/journalctl.c
test/units/testsuite-44.sh

index 0b40f04eb1a47c9b6a1042d144cc52fa5fc8da48..550e2be686ccf73ad0c3d474ec05021da78e7d21 100644 (file)
@@ -45,7 +45,8 @@ _journalctl() {
                       --version --list-catalog --update-catalog --list-boots
                       --show-cursor --dmesg -k --pager-end -e -r --reverse
                       --utc -x --catalog --no-full --force --dump-catalog
-                      --flush --rotate --sync --no-hostname -N --fields'
+                      --flush --rotate --sync --no-hostname -N --fields
+                      --list-namespaces'
         [ARG]='-b --boot -D --directory --file -F --field -t --identifier
                       -T --exclude-identifier --facility -M --machine -o --output
                       -u --unit --user-unit -p --priority --root --case-sensitive'
index 5dba1e7dfe1745d8ea8a98d89bf55809d0077b36..7e18d431584e37f50b17ddbdbcfc01f48dc1457a 100644 (file)
@@ -131,6 +131,7 @@ _arguments -s \
     '--header[Show journal header information]' \
     '--interval=[Time interval for changing the FSS sealing key]:time interval' \
     '--list-catalog[List messages in catalog]' \
+    '--list-namespaces[List available journal namespaces]' \
     '--new-id128[Generate a new 128 Bit ID]' \
     '--rotate[Request immediate rotation of the journal files]' \
     '--setup-keys[Generate a new FSS key pair]' \
index c26d7f1defae4ce4b8c46b640e2165cdbb511323..cc476c30db764e918ba4daba5bbe2d69cbb49580 100644 (file)
@@ -28,6 +28,7 @@
 #include "chattr-util.h"
 #include "constants.h"
 #include "devnum-util.h"
+#include "dirent-util.h"
 #include "dissect-image.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -175,6 +176,7 @@ static enum {
         ACTION_ROTATE_AND_VACUUM,
         ACTION_LIST_FIELDS,
         ACTION_LIST_FIELD_NAMES,
+        ACTION_LIST_NAMESPACES,
 } arg_action = ACTION_SHOW;
 
 static int add_matches_for_device(sd_journal *j, const char *devpath) {
@@ -491,6 +493,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_HOSTNAME,
                 ARG_OUTPUT_FIELDS,
                 ARG_NAMESPACE,
+                ARG_LIST_NAMESPACES,
         };
 
         static const struct option options[] = {
@@ -561,6 +564,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "no-hostname",          no_argument,       NULL, ARG_NO_HOSTNAME          },
                 { "output-fields",        required_argument, NULL, ARG_OUTPUT_FIELDS        },
                 { "namespace",            required_argument, NULL, ARG_NAMESPACE            },
+                { "list-namespaces",      no_argument,       NULL, ARG_LIST_NAMESPACES      },
                 {}
         };
 
@@ -727,6 +731,10 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_LIST_NAMESPACES:
+                        arg_action = ACTION_LIST_NAMESPACES;
+                        break;
+
                 case 'D':
                         arg_directory = optarg;
                         break;
@@ -1229,6 +1237,64 @@ static int add_matches(sd_journal *j, char **args) {
         return 0;
 }
 
+static int list_namespaces(const char *root) {
+        _cleanup_(table_unrefp) Table *table = NULL;
+        sd_id128_t machine;
+        char machine_id[SD_ID128_STRING_MAX];
+        int r;
+
+        r = sd_id128_get_machine(&machine);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get machine ID: %m");
+
+        sd_id128_to_string(machine, machine_id);
+
+        table = table_new("namespace");
+        if (!table)
+                return log_oom();
+
+        (void) table_set_sort(table, (size_t) 0);
+
+        FOREACH_STRING(dir, "/var/log/journal", "/run/log/journal") {
+                _cleanup_free_ char *path = NULL;
+                _cleanup_closedir_ DIR *dirp = NULL;
+
+                path = path_join(root, dir);
+                if (!path)
+                        return log_oom();
+
+                dirp = opendir(path);
+                if (!dirp) {
+                        log_debug_errno(errno, "Failed to open directory %s, ignoring: %m", path);
+                        continue;
+                }
+
+                FOREACH_DIRENT(de, dirp, return log_error_errno(errno, "Failed to iterate through %s: %m", path)) {
+                        char *dot;
+
+                        if (!startswith(de->d_name, machine_id))
+                                continue;
+
+                        dot = strchr(de->d_name, '.');
+                        if (!dot)
+                                continue;
+
+                        if (!log_namespace_name_valid(dot + 1))
+                                continue;
+
+                        r = table_add_cell(table, NULL, TABLE_STRING, dot + 1);
+                        if (r < 0)
+                                return table_log_add_error(r);
+                }
+        }
+
+        r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet);
+        if (r < 0)
+                return table_log_print_error(r);
+
+        return 0;
+}
+
 static int list_boots(sd_journal *j) {
         _cleanup_(table_unrefp) Table *table = NULL;
         _cleanup_free_ BootId *boots = NULL;
@@ -2288,6 +2354,9 @@ static int run(int argc, char *argv[]) {
         case ACTION_ROTATE:
                 return rotate();
 
+        case ACTION_LIST_NAMESPACES:
+                return list_namespaces(arg_root);
+
         case ACTION_SHOW:
         case ACTION_PRINT_HEADER:
         case ACTION_VERIFY:
index fbd4ae692c0c4df6288dadea1f952d1987cc8471..cc5f08f32afb491a3aa7670a0113cb826127daf6 100755 (executable)
@@ -4,12 +4,20 @@ set -eux
 
 systemd-analyze log-level debug
 
+journalctl --list-namespaces -o json | jq .
+
 systemd-run --wait -p LogNamespace=foobar echo "hello world"
+systemd-run --wait -p LogNamespace=foobaz echo "hello world"
 
 journalctl --namespace=foobar --sync
 journalctl -o cat --namespace=foobar >/tmp/hello-world
 journalctl -o cat >/tmp/no-hello-world
 
+journalctl --list-namespaces | grep foobar
+journalctl --list-namespaces | grep foobaz
+journalctl --list-namespaces -o json | jq .
+[[ "$(journalctl --root=/tmp --list-namespaces --quiet)" == "" ]]
+
 grep "^hello world$" /tmp/hello-world
 (! grep "^hello world$" /tmp/no-hello-world)