diff options
-rw-r--r-- | man/systemd-run.xml | 13 | ||||
-rw-r--r-- | src/core/dbus-service.c | 17 | ||||
-rw-r--r-- | src/run/run.c | 43 |
3 files changed, 56 insertions, 17 deletions
diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 3f777b5a4e..707d88d766 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -147,6 +147,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. instead of the <filename>system.slice</filename>.</para> </listitem> </varlistentry> + + <varlistentry> + <term><option>--remain-after-exit</option></term> + + <listitem><para>After the service's process terminated keep + the service around until it is explicitly stopped. This is + useful to collect runtime information about the service after + it finished running. Also see + <varname>RemainAfterExit=</varname> in + <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + </para> + </listitem> + </varlistentry> </variablelist> <para>All command-line arguments after the first non-option diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 8b157b5f3c..1a44e1fd1b 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -180,7 +180,22 @@ static int bus_service_set_transient_property( assert(s); assert(i); - if (streq(name, "ExecStart")) { + if (streq(name, "RemainAfterExit")) { + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN) + return -EINVAL; + + if (mode != UNIT_CHECK) { + dbus_bool_t b; + + dbus_message_iter_get_basic(i, &b); + + s->remain_after_exit = b; + unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b)); + } + + return 1; + + } else if (streq(name, "ExecStart")) { DBusMessageIter sub; unsigned n = 0; diff --git a/src/run/run.c b/src/run/run.c index e56a977de3..c1a0ffb13f 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -31,6 +31,7 @@ static bool arg_scope = false; static bool arg_user = false; +static bool arg_remain_after_exit = false; static const char *arg_unit = NULL; static const char *arg_description = NULL; static const char *arg_slice = NULL; @@ -39,13 +40,14 @@ static int help(void) { printf("%s [OPTIONS...] [COMMAND LINE...]\n\n" "Run the specified command in a transient scope or service unit.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --user Run as user unit\n" - " --scope Run this as scope rather than service\n" - " --unit=UNIT Run under the specified unit name\n" - " --description=TEXT Description for unit\n" - " --slice=SLICE Run in the specified slice\n", + " -h --help Show this help\n" + " --version Show package version\n" + " --user Run as user unit\n" + " --scope Run this as scope rather than service\n" + " --unit=UNIT Run under the specified unit name\n" + " --description=TEXT Description for unit\n" + " --slice=SLICE Run in the specified slice\n" + " -r --remain-after-exit Leave service around until explicitly stopped\n", program_invocation_short_name); return 0; @@ -63,14 +65,15 @@ static int parse_argv(int argc, char *argv[]) { }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "user", no_argument, NULL, ARG_USER }, - { "scope", no_argument, NULL, ARG_SCOPE }, - { "unit", required_argument, NULL, ARG_UNIT }, - { "description", required_argument, NULL, ARG_DESCRIPTION }, - { "slice", required_argument, NULL, ARG_SLICE }, - { NULL, 0, NULL, 0 }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "user", no_argument, NULL, ARG_USER }, + { "scope", no_argument, NULL, ARG_SCOPE }, + { "unit", required_argument, NULL, ARG_UNIT }, + { "description", required_argument, NULL, ARG_DESCRIPTION }, + { "slice", required_argument, NULL, ARG_SLICE }, + { "remain-after-exit", required_argument, NULL, 'r' }, + { NULL, 0, NULL, 0 }, }; int c; @@ -78,7 +81,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+h", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "+hr", options, NULL)) >= 0) { switch (c) { @@ -111,6 +114,10 @@ static int parse_argv(int argc, char *argv[]) { arg_slice = optarg; break; + case 'r': + arg_remain_after_exit = true; + break; + case '?': return -EINVAL; @@ -204,6 +211,10 @@ static int start_transient_service( if (r < 0) return r; + r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit); + if (r < 0) + return r; + r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) return r; |