From c2756a68401102786be343712c0c35acbd73d28d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Jun 2013 04:12:58 +0200 Subject: core: add transient units Transient units can be created via the bus API. They are configured via the method call parameters rather than on-disk files. They are subject to normal GC. Transient units currently may only be created for services (however, we will extend this), and currently only ExecStart= and the cgroup parameters can be configured (also to be extended). Transient units require a unique name, that previously had no configuration file on disk. A tool systemd-run is added that makes use of this functionality to run arbitrary command lines as transient services: $ systemd-run /bin/ping www.heise.de Will cause systemd to create a new transient service and run ping in it. --- src/run/run.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/run/run.c (limited to 'src/run/run.c') diff --git a/src/run/run.c b/src/run/run.c new file mode 100644 index 0000000000..9f8bda48af --- /dev/null +++ b/src/run/run.c @@ -0,0 +1,156 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "sd-bus.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "strv.h" + +static int start_transient_service( + sd_bus *bus, + const char *name, + char **argv, + sd_bus_error *error) { + + _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + char **i; + int r; + + r = sd_bus_message_new_method_call( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit", &m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "ss", name, "fail"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'r', "sv"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", "ExecStart"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'v', "a(sasb)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "(sasb)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'r', "sasb"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", argv[0]); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return r; + + STRV_FOREACH(i, argv) { + r = sd_bus_message_append(m, "s", *i); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "b", false); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + return sd_bus_send_with_reply_and_block(bus, m, 0, error, &reply); +} + +int main(int argc, char* argv[]) { + sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; + _cleanup_free_ char *name = NULL; + int r; + + log_parse_environment(); + log_open(); + + if (argc < 2) { + log_error("Missing command line."); + r = -EINVAL; + goto fail; + } + + r = sd_bus_open_user(&bus); + if (r < 0) { + log_error("Failed to create new bus: %s", strerror(-r)); + goto fail; + } + + if (asprintf(&name, "run-%lu.service", (unsigned long) getpid()) < 0) { + r = log_oom(); + goto fail; + } + + r = start_transient_service(bus, name, argv + 1, &error); + if (r < 0) { + log_error("Failed start transient service: %s", error.message); + sd_bus_error_free(&error); + goto fail; + } + +fail: + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} -- cgit v1.2.3-54-g00ecf