run.c revision 8159d91a9c92aaee66d450ab0daff88f6e1a42b3
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering This file is part of systemd.
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering Copyright 2013 Lennart Poettering
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering systemd is free software; you can redistribute it and/or modify it
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering under the terms of the GNU Lesser General Public License as published by
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering (at your option) any later version.
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering systemd is distributed in the hope that it will be useful, but
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering Lesser General Public License for more details.
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering You should have received a copy of the GNU Lesser General Public License
c2756a68401102786be343712c0c35acbd73d28dLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringstatic bool arg_scope = false;
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poetteringstatic bool arg_remain_after_exit = false;
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersenstatic const char *arg_unit = NULL;
4bcc8c3cb57733de6eeb2528a194501fade11e6bZbigniew Jędrzejewski-Szmekstatic const char *arg_description = NULL;
24882e06c135584f16f31ba8a00fecde8b7f6fadLennart Poetteringstatic bool arg_send_sighup = false;
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchaginstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
66cb2fde7b0ab6603775ad13c30c004f5fd88f0cLennart Poetteringstatic bool arg_user = false;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringstatic int help(void) {
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin printf("%s [OPTIONS...] COMMAND [ARGS...]\n\n"
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering "Run the specified command in a transient scope or service unit.\n\n"
6577c7cea72f19185ad999c223bcf663c010dc6fLennart Poettering " -h --help Show this help\n"
3d161f991e16369aa59f447eb4cdb90af33261c8Lennart Poettering " --version Show package version\n"
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering " --user Run as user unit\n"
9f2e86af0600e99cff00d1c92f9bb8d38f29896aLennart Poettering " -H --host=[USER@]HOST Operate on remote host\n"
c221420be8744bb0f8b8a8145efc1f247f1aa801Lennart Poettering " -M --machine=CONTAINER Operate on local container\n"
a6c0353b9268d5b780fb7ff05a10cb5031446e5dLennart Poettering " --scope Run this as scope rather than service\n"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering " --unit=UNIT Run under the specified unit name\n"
1ac67edb7c4d31a287fa98c0b554ae98bd34e71bLennart Poettering " --description=TEXT Description for unit\n"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering " --slice=SLICE Run in the specified slice\n"
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering " -r --remain-after-exit Leave service around until explicitly stopped\n"
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering " --send-sighup Send SIGHUP when terminating\n",
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin static const struct option options[] = {
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "version", no_argument, NULL, ARG_VERSION },
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "user", no_argument, NULL, ARG_USER },
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "system", no_argument, NULL, ARG_SYSTEM },
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "scope", no_argument, NULL, ARG_SCOPE },
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "unit", required_argument, NULL, ARG_UNIT },
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "description", required_argument, NULL, ARG_DESCRIPTION },
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin { "slice", required_argument, NULL, ARG_SLICE },
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek { "remain-after-exit", no_argument, NULL, 'r' },
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho while ((c = getopt_long(argc, argv, "+hrH:M:", options, NULL)) >= 0) {
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho switch (c) {
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) {
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho log_error("Execution in user context is not supported on non-local systems.");
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) {
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho log_error("Scope execution is not supported on non-local systems.");
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Chostatic int message_start_transient_unit_new(sd_bus *bus, const char *name, sd_bus_message **ret) {
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering "org.freedesktop.systemd1.Manager",
095dc59660c3dde782f32fe5a52b577f7700578bLennart Poettering "StartTransientUnit", &m);
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering r = sd_bus_message_append(m, "ss", name, "fail");
8c7db2fb2186277f9572d58b664cc59792ee4f50Evgeny Vereshchagin r = sd_bus_message_open_container(m, 'a', "(sv)");
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
66b1e746055b9c56fd72c0451a4cfb2b06cf3f20Lennart Poettering slice = unit_name_mangle_with_suffix(arg_slice, ".slice");
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
c221420be8744bb0f8b8a8145efc1f247f1aa801Lennart Poetteringstatic int message_start_transient_unit_send(sd_bus *bus, sd_bus_message *m, sd_bus_error *error, sd_bus_message **reply) {
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering name = unit_name_mangle_with_suffix(arg_unit, ".service");
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering asprintf(&name, "run-%lu.service", (unsigned long) getpid());
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering r = message_start_transient_unit_new(bus, name, &m);
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering r = sd_bus_message_open_container(m, 'r', "sv");
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering r = sd_bus_message_append(m, "s", "ExecStart");
c7040b5d1c2c148f12b6a5eef3dfce1661805131Lennart Poettering r = sd_bus_message_open_container(m, 'v', "a(sasb)");
df31a6c0fe07805cb50045fbe91c2a6e7e430562Lennart Poettering r = sd_bus_message_open_container(m, 'a', "(sasb)");
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poettering r = sd_bus_message_open_container(m, 'r', "sasb");
095dc59660c3dde782f32fe5a52b577f7700578bLennart Poettering r = sd_bus_message_append(m, "s", argv[0]);
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho return message_start_transient_unit_send(bus, m, error, NULL);
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
024a8ec137f17cbbc22256ef4aa7f99ec671dbc5Lennart Poettering name = unit_name_mangle_with_suffix(arg_unit, ".scope");
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho asprintf(&name, "run-%lu.scope", (unsigned long) getpid());
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho r = message_start_transient_unit_new(bus, name, &m);
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho r = message_start_transient_unit_send(bus, m, error, NULL);
3d161f991e16369aa59f447eb4cdb90af33261c8Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6c12b52e19640747e96f89d85422941a23dc6b29Lennart Poettering _cleanup_free_ char *description = NULL, *command = NULL;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering log_error("Failed to find executable %s: %s", argv[optind], strerror(-r));
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering description = strv_join(argv + optind, " ");
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poettering r = bus_open_transport(arg_transport, arg_host, arg_user, &bus);
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poettering log_error("Failed to create bus connection: %s", strerror(-r));
024a8ec137f17cbbc22256ef4aa7f99ec671dbc5Lennart Poettering r = start_transient_scope(bus, argv + optind, &error);
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho r = start_transient_service(bus, argv + optind, &error);
4c213d6cf416917c61f82d8bee795b8f3a4c5372WaLyong Cho log_error("Failed start transient unit: %s", bus_error_message(&error, r));