]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journalctl: make --invocation and --list-invocations accept unit name with glob 35542/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 11 Dec 2024 00:35:32 +0000 (09:35 +0900)
committerLuca Boccassi <bluca@debian.org>
Wed, 11 Dec 2024 16:32:22 +0000 (16:32 +0000)
Previously, journalctl -I -u GLOB was not supported, while
journalctl -u GLOB works fine. Let's make them consistent.

src/journal/journalctl-misc.c
src/journal/journalctl-util.c
src/journal/journalctl-util.h
test/units/TEST-04-JOURNAL.invocation.sh

index 3dea69d9fb3dd5ea018afe68f542191909b112da..46a70ae1ac566e7d5177879de0fa5a5832e45f1b 100644 (file)
@@ -246,11 +246,11 @@ int action_list_invocations(void) {
 
         assert(arg_action == ACTION_LIST_INVOCATIONS);
 
-        r = acquire_unit("--list-invocations", &unit, &type);
+        r = acquire_journal(&j);
         if (r < 0)
                 return r;
 
-        r = acquire_journal(&j);
+        r = acquire_unit(j, "--list-invocations", &unit, &type);
         if (r < 0)
                 return r;
 
index 82ddb64f2b3fdf8bc190e7fa6f57a0149606bb90..918e5713f6d0fc6df663cf93ac8505716a68e0fc 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <unistd.h>
 
+#include "glob-util.h"
 #include "id128-util.h"
 #include "journal-util.h"
 #include "journalctl.h"
@@ -163,10 +164,11 @@ int get_possible_units(
         return 0;
 }
 
-int acquire_unit(const char *option_name, const char **ret_unit, LogIdType *ret_type) {
+int acquire_unit(sd_journal *j, const char *option_name, const char **ret_unit, LogIdType *ret_type) {
         size_t n;
         int r;
 
+        assert(j);
         assert(option_name);
         assert(ret_unit);
         assert(ret_type);
@@ -193,11 +195,29 @@ int acquire_unit(const char *option_name, const char **ret_unit, LogIdType *ret_
         }
 
         _cleanup_free_ char *u = NULL;
-        r = unit_name_mangle(units[0], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &u);
+        r = unit_name_mangle(units[0], UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
         if (r < 0)
                 return log_error_errno(r, "Failed to mangle unit name '%s': %m", units[0]);
 
-        free_and_replace(units[0], u);
+        if (string_is_glob(u)) {
+                _cleanup_set_free_ Set *s = NULL;
+
+                r = get_possible_units(j, type == LOG_SYSTEM_UNIT_INVOCATION_ID ? SYSTEM_UNITS : USER_UNITS,
+                                       STRV_MAKE(u), &s);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get matching unit '%s' from journal: %m", u);
+                if (set_isempty(s))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No matching unit found for '%s' in journal.", u);
+                if (set_size(s) > 1)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple matching units found for '%s' in journal.", u);
+
+                char *found = set_steal_first(s);
+                log_debug("Found matching unit '%s' for '%s'.", found, u);
+
+                free_and_replace(units[0], found);
+                assert(set_isempty(s));
+        } else
+                free_and_replace(units[0], u);
 
         *ret_type = type;
         *ret_unit = units[0];
@@ -225,7 +245,7 @@ int journal_acquire_invocation(sd_journal *j) {
          * system unit or user unit, and calling without unit name is allowed. Otherwise, a unit name must
          * be specified. */
         if (arg_invocation_offset != 0 || sd_id128_is_null(arg_invocation_id)) {
-                r = acquire_unit("-I/--invocation= with an offset", &unit, &type);
+                r = acquire_unit(j, "-I/--invocation= with an offset", &unit, &type);
                 if (r < 0)
                         return r;
         }
index 49a4d3e08b045548a5b58658bac5f0db7d6693f3..14cdfb51361bb74a2c1deec97e50b52799dbecd5 100644 (file)
@@ -34,5 +34,5 @@ int acquire_journal(sd_journal **ret);
 bool journal_boot_has_effect(sd_journal *j);
 int journal_acquire_boot(sd_journal *j);
 int get_possible_units(sd_journal *j, const char *fields, char * const *patterns, Set **ret);
-int acquire_unit(const char *option_name, const char **ret_unit, LogIdType *ret_type);
+int acquire_unit(sd_journal *j, const char *option_name, const char **ret_unit, LogIdType *ret_type);
 int journal_acquire_invocation(sd_journal *j);
index 3ac931e26330ec318367465ed3125af2c024a124..74db1040fdf627c9a8419ef5307882c381219d63 100755 (executable)
@@ -7,8 +7,10 @@ set -o pipefail
 # shellcheck source=test/units/util.sh
 . "$(dirname "$0")"/util.sh
 
-SERVICE_NAME_SHORT=invocation-id-test-"$RANDOM"
+BASE=test-"$RANDOM"
+SERVICE_NAME_SHORT=invocation-id-"$BASE"
 SERVICE_NAME="$SERVICE_NAME_SHORT".service
+SERVICE_NAME_GLOB="invocation-*-${BASE}.service"
 
 TMP_DIR=$(mktemp -d)
 
@@ -28,6 +30,7 @@ done
 journalctl --sync
 
 journalctl --list-invocation -u "$SERVICE_NAME_SHORT" | tee "$TMP_DIR"/short
+journalctl --list-invocation -u "$SERVICE_NAME_GLOB" | tee "$TMP_DIR"/glob
 journalctl --list-invocation -u "$SERVICE_NAME" | tee "$TMP_DIR"/10
 journalctl --list-invocation -u "$SERVICE_NAME" --reverse | tee "$TMP_DIR"/10-r
 journalctl --list-invocation -u "$SERVICE_NAME" -n +10 | tee "$TMP_DIR"/p10
@@ -47,6 +50,7 @@ journalctl --list-invocation -u "$SERVICE_NAME" -n +5 --reverse | tee "$TMP_DIR"
 [[ $(cat "$TMP_DIR"/p5-r | wc -l) == 6 ]]
 
 diff "$TMP_DIR"/10 "$TMP_DIR"/short
+diff "$TMP_DIR"/10 "$TMP_DIR"/glob
 diff <(tail -n 10 "$TMP_DIR"/10 | tac) <(tail -n 10 "$TMP_DIR"/10-r)
 diff <(tail -n 5 "$TMP_DIR"/10) <(tail -n 5 "$TMP_DIR"/5)
 diff <(tail -n 5 "$TMP_DIR"/10 | tac) <(tail -n 5 "$TMP_DIR"/5-r)
@@ -59,6 +63,8 @@ tail -n 10 "$TMP_DIR"/10 |
         i="$(( idx + 10 ))"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${i}" -u "$SERVICE_NAME_SHORT")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${idx}" -u "$SERVICE_NAME_SHORT")"
+        assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${i}" -u "$SERVICE_NAME_GLOB")"
+        assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${idx}" -u "$SERVICE_NAME_GLOB")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${i}" -u "$SERVICE_NAME")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${idx}" -u "$SERVICE_NAME")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${invocation}")"
@@ -69,6 +75,8 @@ tail -n 10 "$TMP_DIR"/p10 |
         idx="$(( i - 10 ))"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${i}" -u "$SERVICE_NAME_SHORT")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${idx}" -u "$SERVICE_NAME_SHORT")"
+        assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${i}" -u "$SERVICE_NAME_GLOB")"
+        assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${idx}" -u "$SERVICE_NAME_GLOB")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${i}" -u "$SERVICE_NAME")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${idx}" -u "$SERVICE_NAME")"
         assert_in "invocation ${i} ${invocation}" "$(journalctl --no-hostname -n 1 -t bash --invocation="${invocation}")"