]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemd-run: add unit and invocation_id JSON output
authorLukas Nykryn <lnykryn@redhat.com>
Mon, 12 Aug 2024 13:15:15 +0000 (15:15 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 12 Aug 2024 18:19:01 +0000 (20:19 +0200)
man/systemd-run.xml
shell-completion/bash/systemd-run
shell-completion/zsh/_systemd-run
src/run/run.c
test/units/TEST-74-AUX-UTILS.run.sh

index e1986c1f52fdc51fe4d1b483f75e37ab7a650139..83c62afb5926b76e6711aa7cb1705b7c0ce5d219 100644 (file)
 
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
+      <xi:include href="standard-options.xml" xpointer="json" />
     </variablelist>
 
     <para>All command line arguments after the first non-option argument become part of the command line of
index 4bc82060e9438610730a5690a6c4c99e02e343d8..4537211ae55a0e0ae11c4fddb126e2dfe72faf96 100644 (file)
@@ -38,7 +38,7 @@ _systemd_run() {
         --unit -p --property --slice --description --service-type --uid --gid --nice --working-directory
         -E --setenv --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar
         --path-property --socket-property --timer-property -H --host -M --machine --expand-environment
-        --background
+        --background --json
     )
     local OPTS="${opts_with_values[*]} --no-ask-password --scope -u --slice-inherit -r --remain-after-exit
                 --send-sighup -d --same-dir -t --pty -P --pipe -S --shell -q --quiet --ignore-failure
@@ -126,6 +126,11 @@ _systemd_run() {
             COMPREPLY=( $(compgen -W '$comps' -- "$cur" ) )
             return 0
             ;;
+        --json)
+            local comps='pretty short off'
+            COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+            return 0
+            ;;
     esac
 
     COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
index d3ec2e28efe5c3ddfefb95a30bb3434512a1c476..4bb864da219dc67d96985235db3b3028969805b5 100644 (file)
@@ -59,6 +59,7 @@ _arguments \
                 ))' \
     '(-t --pty)'{-t,--pty}'[The service connects to the terminal]' \
     '(-q --quiet)'{-q,--quiet}'[Suppresses additional informational output]' \
+    '--json=[Output as JSON]:JSON:(pretty short off)' \
     '(-r --remain-after-exit)'{-r,--remain-after-exit}'[Leave service around until explicitly stopped]' \
     '(-d --same-dir)'{-d,--same-dir}'[Run on the current working directory]' \
     '--scope[Run this as scope rather than service]' \
index e86e89b51b386e7243be7d32dcd00733fe6a17cd..62140062ab30e86bed2e138f026064e4c282ba54 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "sd-bus.h"
 #include "sd-event.h"
+#include "sd-json.h"
 
 #include "alloc-util.h"
 #include "build.h"
@@ -83,6 +84,7 @@ static char **arg_cmdline = NULL;
 static char *arg_exec_path = NULL;
 static bool arg_ignore_failure = false;
 static char *arg_background = NULL;
+static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
 
 STATIC_DESTRUCTOR_REGISTER(arg_description, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
@@ -133,6 +135,7 @@ static int help(void) {
                "                                  STDERR\n"
                "  -P --pipe                       Pass STDIN/STDOUT/STDERR directly to service\n"
                "  -q --quiet                      Suppress information messages during runtime\n"
+               "     --json=pretty|short|off      Print unit name and invocation id as JSON\n"
                "  -G --collect                    Unload unit after it ran, even when failed\n"
                "  -S --shell                      Invoke a $SHELL interactively\n"
                "     --ignore-failure             Ignore the exit status of the invoked process\n"
@@ -263,6 +266,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SHELL,
                 ARG_IGNORE_FAILURE,
                 ARG_BACKGROUND,
+                ARG_JSON,
         };
 
         static const struct option options[] = {
@@ -311,6 +315,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "shell",              no_argument,       NULL, 'S'                    },
                 { "ignore-failure",     no_argument,       NULL, ARG_IGNORE_FAILURE     },
                 { "background",         required_argument, NULL, ARG_BACKGROUND         },
+                { "json",               required_argument, NULL, ARG_JSON               },
                 {},
         };
 
@@ -618,6 +623,12 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_JSON:
+                        r = parse_json_argument(optarg, &arg_json_format_flags);
+                        if (r <= 0)
+                                return r;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -1686,6 +1697,33 @@ static int chown_to_capsule(const char *path, const char *capsule) {
         return chmod_and_chown(path, 0600, st.st_uid, st.st_gid);
 }
 
+static int print_unit_invocation(const char *unit, sd_id128_t invocation_id) {
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+        int r;
+
+        assert(unit);
+
+        if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
+                if (sd_id128_is_null(invocation_id))
+                        log_info("Running as unit: %s", unit);
+                else
+                        log_info("Running as unit: %s; invocation ID: " SD_ID128_FORMAT_STR, unit, SD_ID128_FORMAT_VAL(invocation_id));
+                return 0;
+        }
+
+        r = sd_json_variant_set_field_string(&v, "unit", unit);
+        if (r < 0)
+                return r;
+
+        if (!sd_id128_is_null(invocation_id)) {
+                r = sd_json_variant_set_field_string(&v, "invocation_id", SD_ID128_TO_STRING(invocation_id));
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_json_variant_dump(v, arg_json_format_flags, stdout, NULL);
+}
+
 static int start_transient_service(sd_bus *bus) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -1807,15 +1845,15 @@ static int start_transient_service(sd_bus *bus) {
         }
 
         if (!arg_quiet) {
-                sd_id128_t invocation_id;
+                sd_id128_t invocation_id = SD_ID128_NULL;
 
                 r = acquire_invocation_id(bus, service, &invocation_id);
                 if (r < 0)
                         return r;
-                if (r == 0) /* No invocation UUID set */
-                        log_info("Running as unit: %s", service);
-                else
-                        log_info("Running as unit: %s; invocation ID: " SD_ID128_FORMAT_STR, service, SD_ID128_FORMAT_VAL(invocation_id));
+
+                r = print_unit_invocation(service, invocation_id);
+                if (r < 0)
+                        return r;
         }
 
         if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
@@ -1976,7 +2014,7 @@ static int start_transient_scope(sd_bus *bus) {
         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
         _cleanup_free_ char *scope = NULL;
         const char *object = NULL;
-        sd_id128_t invocation_id;
+        sd_id128_t invocation_id = SD_ID128_NULL;
         bool allow_pidfd = true;
         int r;
 
@@ -2131,10 +2169,9 @@ static int start_transient_scope(sd_bus *bus) {
                 return log_oom();
 
         if (!arg_quiet) {
-                if (sd_id128_is_null(invocation_id))
-                        log_info("Running as unit: %s", scope);
-                else
-                        log_info("Running as unit: %s; invocation ID: " SD_ID128_FORMAT_STR, scope, SD_ID128_FORMAT_VAL(invocation_id));
+                r = print_unit_invocation(scope, invocation_id);
+                if (r < 0)
+                        return r;
         }
 
         if (arg_expand_environment > 0) {
index b4ff72e440da5a5cbfc462287bd56f68875a4c40..9e0a429e414b60c5d272f9f53232562ae904aad1 100755 (executable)
@@ -205,6 +205,8 @@ SHELL=/bin/true systemd-run --shell
 SHELL=/bin/true systemd-run --scope --shell
 systemd-run --wait --pty true
 systemd-run --wait --machine=.host --pty true
+systemd-run --json=short /bin/true | jq . >/dev/null
+systemd-run --json=pretty /bin/true | jq . >/dev/null
 (! SHELL=/bin/false systemd-run --quiet --shell)
 
 (! systemd-run)