]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
run: allow setting output format
authorArnout Engelen <arnout@bzzt.net>
Mon, 6 Apr 2026 08:00:37 +0000 (10:00 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 13 Apr 2026 11:38:04 +0000 (13:38 +0200)
This is useful when moving from `--pty` or `--pipe` to using
`--verbose`: you can use `--verbose-output=cat` to get similar output on
stdout while still having all of the advantages of `--verbose` over the
other options.

man/systemd-run.xml
src/run/run.c
src/shared/fork-notify.c
src/shared/fork-notify.h
src/systemctl/systemctl-start-unit.c

index d18b80faa8afca4b815b8a76cd8a0e60ab85da47..bb90f352657ed87cf93983da8b246476f037cf3c 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--output=</option></term>
+
+        <listitem>
+          <para>Controls the formatting of verbose unit log output, see <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for possible values.</para>
+
+          <xi:include href="version-info.xml" xpointer="v261"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--on-active=</option></term>
         <term><option>--on-boot=</option></term>
index 88a9f41d69a3aa5511a5eb3aa4d690381c31447a..596e12826753cae127607c12f6762f43a1ee6e5c 100644 (file)
@@ -105,6 +105,7 @@ static char **arg_timer_property = NULL;
 static bool arg_with_timer = false;
 static bool arg_quiet = false;
 static bool arg_verbose = false;
+static OutputMode arg_output = _OUTPUT_MODE_INVALID;
 static bool arg_aggressive_gc = false;
 static char *arg_working_directory = NULL;
 static char *arg_root_directory = NULL;
@@ -182,6 +183,8 @@ static int help(void) {
                "  -P --pipe                       Pass STDIN/STDOUT/STDERR directly to service\n"
                "  -q --quiet                      Suppress information messages during runtime\n"
                "  -v --verbose                    Show unit logs while executing operation\n"
+               "     --output=STRING              Controls formatting of verbose logs, see\n"
+               "                                  journalctl for valid values\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"
@@ -318,6 +321,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_EXEC_USER,
                 ARG_EXEC_GROUP,
                 ARG_NICE,
+                ARG_OUTPUT,
                 ARG_ON_ACTIVE,
                 ARG_ON_BOOT,
                 ARG_ON_STARTUP,
@@ -370,6 +374,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "pipe",               no_argument,       NULL, 'P'                    },
                 { "quiet",              no_argument,       NULL, 'q'                    },
                 { "verbose",            no_argument,       NULL, 'v'                    },
+                { "output",             required_argument, NULL, ARG_OUTPUT             },
                 { "on-active",          required_argument, NULL, ARG_ON_ACTIVE          },
                 { "on-boot",            required_argument, NULL, ARG_ON_BOOT            },
                 { "on-startup",         required_argument, NULL, ARG_ON_STARTUP         },
@@ -542,6 +547,15 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_verbose = true;
                         break;
 
+                case ARG_OUTPUT:
+                        if (streq(optarg, "help"))
+                                return DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+
+                        arg_output = output_mode_from_string(optarg);
+                        if (arg_output < 0)
+                                return log_error_errno(arg_output, "Unknown output format '%s'.", optarg);
+                        break;
+
                 case ARG_ON_ACTIVE:
                         r = add_timer_property("OnActiveSec", optarg);
                         if (r < 0)
@@ -2569,7 +2583,7 @@ static int start_transient_service(sd_bus *bus) {
 
         _cleanup_(fork_notify_terminate) PidRef journal_pid = PIDREF_NULL;
         if (arg_verbose)
-                (void) journal_fork(arg_runtime_scope, STRV_MAKE(c.unit), &journal_pid);
+                (void) journal_fork(arg_runtime_scope, STRV_MAKE(c.unit), arg_output, &journal_pid);
 
         r = bus_call_with_hint(bus, m, "service", &reply);
         if (r < 0)
index 6f87a2fdce2b296991bce9bcd7cccbdd39bc8598..307197ac197019b1061236465103e4162bff9e5d 100644 (file)
@@ -205,7 +205,7 @@ void fork_notify_terminate_many(sd_event_source **array, size_t n) {
         free(array);
 }
 
-int journal_fork(RuntimeScope scope, char * const* units, PidRef *ret_pidref) {
+int journal_fork(RuntimeScope scope, char * const* units, OutputMode output, PidRef *ret_pidref) {
         assert(scope >= 0);
         assert(scope < _RUNTIME_SCOPE_MAX);
 
@@ -228,5 +228,9 @@ int journal_fork(RuntimeScope scope, char * const* units, PidRef *ret_pidref) {
                                  *u) < 0)
                         return log_oom_debug();
 
+        if (output >= 0)
+                if (strv_extendf(&argv, "--output=%s", output_mode_to_string(output)) < 0)
+                        return log_oom_debug();
+
         return fork_notify(argv, ret_pidref);
 }
index 103ab78983371af5eab8a6ba6e6abf5f1273ee65..2dbfe368a4664f9972249ec5a9e57c1d113e272c 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "output-mode.h"
 #include "shared-forward.h"
 
 int fork_notify(char * const *argv, PidRef *ret_pidref);
@@ -9,4 +10,4 @@ void fork_notify_terminate(PidRef *pidref);
 
 void fork_notify_terminate_many(sd_event_source **array, size_t n);
 
-int journal_fork(RuntimeScope scope, char * const *units, PidRef *ret_pidref);
+int journal_fork(RuntimeScope scope, char * const *units, OutputMode output, PidRef *ret_pidref);
index 0c8582bdff7104ef5f19929837cca2fcc7e5392c..1b6dbd8b14040ea0eee45bbf59e10e2c893b43c4 100644 (file)
@@ -402,7 +402,7 @@ int verb_start(int argc, char *argv[], uintptr_t _data, void *userdata) {
                 ret = enqueue_marked_jobs(bus, w);
         else {
                 if (arg_verbose)
-                        (void) journal_fork(arg_runtime_scope, names, &journal_pid);
+                        (void) journal_fork(arg_runtime_scope, names, arg_output, &journal_pid);
 
                 STRV_FOREACH(name, names) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;