mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 16:21:26 +03:00
run: add support to create transient path and socket unit
This commit is contained in:
parent
89ada3ba08
commit
d59ef3e243
@ -69,6 +69,8 @@ static enum {
|
||||
ARG_STDIO_DIRECT, /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */
|
||||
ARG_STDIO_AUTO, /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */
|
||||
} arg_stdio = ARG_STDIO_NONE;
|
||||
static char **arg_path_property = NULL;
|
||||
static char **arg_socket_property = NULL;
|
||||
static char **arg_timer_property = NULL;
|
||||
static bool with_timer = false;
|
||||
static bool arg_quiet = false;
|
||||
@ -102,6 +104,10 @@ static void help(void) {
|
||||
" -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n"
|
||||
" -q --quiet Suppress information messages during runtime\n"
|
||||
" -G --collect Unload unit after it ran, even when failed\n\n"
|
||||
"Path options:\n"
|
||||
" --path-property=NAME=VALUE Set path unit property\n\n"
|
||||
"Socket options:\n"
|
||||
" --socket-property=NAME=VALUE Set socket unit property\n\n"
|
||||
"Timer options:\n"
|
||||
" --on-active=SECONDS Run after SECONDS delay\n"
|
||||
" --on-boot=SECONDS Run SECONDS after machine was booted up\n"
|
||||
@ -153,6 +159,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_ON_UNIT_INACTIVE,
|
||||
ARG_ON_CALENDAR,
|
||||
ARG_TIMER_PROPERTY,
|
||||
ARG_PATH_PROPERTY,
|
||||
ARG_SOCKET_PROPERTY,
|
||||
ARG_NO_BLOCK,
|
||||
ARG_NO_ASK_PASSWORD,
|
||||
ARG_WAIT,
|
||||
@ -189,12 +197,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
|
||||
{ "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
|
||||
{ "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
|
||||
{ "path-property", required_argument, NULL, ARG_PATH_PROPERTY },
|
||||
{ "socket-property", required_argument, NULL, ARG_SOCKET_PROPERTY },
|
||||
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
|
||||
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
||||
{ "collect", no_argument, NULL, 'G' },
|
||||
{},
|
||||
};
|
||||
|
||||
bool with_trigger = false;
|
||||
int r, c;
|
||||
|
||||
assert(argc >= 0);
|
||||
@ -369,6 +380,20 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
!!startswith(optarg, "OnCalendar=");
|
||||
break;
|
||||
|
||||
case ARG_PATH_PROPERTY:
|
||||
|
||||
if (strv_extend(&arg_path_property, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_SOCKET_PROPERTY:
|
||||
|
||||
if (strv_extend(&arg_socket_property, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_NO_BLOCK:
|
||||
arg_no_block = true;
|
||||
break;
|
||||
@ -388,6 +413,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
with_trigger = !!arg_path_property || !!arg_socket_property || with_timer;
|
||||
|
||||
/* currently, only single trigger (path, socket, timer) unit can be created simultaneously */
|
||||
if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) with_timer > 1) {
|
||||
log_error("Only single trigger (path, socket, timer) unit can be created.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_stdio == ARG_STDIO_AUTO) {
|
||||
/* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
|
||||
@ -398,7 +430,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_STDIO_DIRECT;
|
||||
}
|
||||
|
||||
if ((optind >= argc) && (!arg_unit || !with_timer)) {
|
||||
if ((optind >= argc) && (!arg_unit || !with_trigger)) {
|
||||
log_error("Command line to execute required.");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -418,7 +450,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_stdio != ARG_STDIO_NONE && (with_timer || arg_scope)) {
|
||||
if (arg_stdio != ARG_STDIO_NONE && (with_trigger || arg_scope)) {
|
||||
log_error("--pty/--pipe is not compatible in timer or --scope mode.");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -433,8 +465,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_scope && with_timer) {
|
||||
log_error("Timer options are not supported in --scope mode.");
|
||||
if (arg_scope && with_trigger) {
|
||||
log_error("Path, socket or timer options are not supported in --scope mode.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -449,8 +481,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (with_timer) {
|
||||
log_error("--wait may not be combined with timer operations.");
|
||||
if (with_trigger) {
|
||||
log_error("--wait may not be combined with path, socket or timer operations.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1283,14 +1315,15 @@ static int start_transient_scope(
|
||||
return log_error_errno(errno, "Failed to execute: %m");
|
||||
}
|
||||
|
||||
static int start_transient_timer(
|
||||
static int start_transient_trigger(
|
||||
sd_bus *bus,
|
||||
char **argv) {
|
||||
char **argv,
|
||||
const char *suffix) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||
_cleanup_free_ char *timer = NULL, *service = NULL;
|
||||
_cleanup_free_ char *trigger = NULL, *service = NULL;
|
||||
const char *object = NULL;
|
||||
int r;
|
||||
|
||||
@ -1309,17 +1342,17 @@ static int start_transient_timer(
|
||||
if (!service)
|
||||
return log_oom();
|
||||
|
||||
r = unit_name_change_suffix(service, ".timer", &timer);
|
||||
r = unit_name_change_suffix(service, suffix, &trigger);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change unit suffix: %m");
|
||||
break;
|
||||
|
||||
case UNIT_TIMER:
|
||||
timer = strdup(arg_unit);
|
||||
if (!timer)
|
||||
trigger = strdup(arg_unit);
|
||||
if (!trigger)
|
||||
return log_oom();
|
||||
|
||||
r = unit_name_change_suffix(timer, ".service", &service);
|
||||
r = unit_name_change_suffix(trigger, ".service", &service);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change unit suffix: %m");
|
||||
break;
|
||||
@ -1329,7 +1362,7 @@ static int start_transient_timer(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle unit name: %m");
|
||||
|
||||
r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
|
||||
r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, suffix, &trigger);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle unit name: %m");
|
||||
|
||||
@ -1340,7 +1373,7 @@ static int start_transient_timer(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_name_change_suffix(service, ".timer", &timer);
|
||||
r = unit_name_change_suffix(service, suffix, &trigger);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change unit suffix: %m");
|
||||
}
|
||||
@ -1360,7 +1393,7 @@ static int start_transient_timer(
|
||||
return bus_log_create_error(r);
|
||||
|
||||
/* Name and Mode */
|
||||
r = sd_bus_message_append(m, "ss", timer, "fail");
|
||||
r = sd_bus_message_append(m, "ss", trigger, "fail");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
@ -1369,7 +1402,14 @@ static int start_transient_timer(
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = transient_timer_set_properties(m);
|
||||
if (streq(suffix, ".path"))
|
||||
r = transient_unit_set_properties(m, UNIT_PATH, arg_path_property);
|
||||
else if (streq(suffix, ".socket"))
|
||||
r = transient_unit_set_properties(m, UNIT_SOCKET, arg_socket_property);
|
||||
else if (streq(suffix, ".timer"))
|
||||
r = transient_timer_set_properties(m);
|
||||
else
|
||||
assert_not_reached("Invalid suffix");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1415,7 +1455,7 @@ static int start_transient_timer(
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, &reply);
|
||||
if (r < 0) {
|
||||
log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
|
||||
log_error("Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, -r));
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1428,7 +1468,7 @@ static int start_transient_timer(
|
||||
return r;
|
||||
|
||||
if (!arg_quiet) {
|
||||
log_info("Running timer as unit: %s", timer);
|
||||
log_info("Running %s as unit: %s", suffix + 1, trigger);
|
||||
if (argv[0])
|
||||
log_info("Will run service as unit: %s", service);
|
||||
}
|
||||
@ -1489,14 +1529,20 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (arg_scope)
|
||||
r = start_transient_scope(bus, argv + optind);
|
||||
else if (arg_path_property)
|
||||
r = start_transient_trigger(bus, argv + optind, ".path");
|
||||
else if (arg_socket_property)
|
||||
r = start_transient_trigger(bus, argv + optind, ".socket");
|
||||
else if (with_timer)
|
||||
r = start_transient_timer(bus, argv + optind);
|
||||
r = start_transient_trigger(bus, argv + optind, ".timer");
|
||||
else
|
||||
r = start_transient_service(bus, argv + optind, &retval);
|
||||
|
||||
finish:
|
||||
strv_free(arg_environment);
|
||||
strv_free(arg_property);
|
||||
strv_free(arg_path_property);
|
||||
strv_free(arg_socket_property);
|
||||
strv_free(arg_timer_property);
|
||||
|
||||
return r < 0 ? EXIT_FAILURE : retval;
|
||||
|
Loading…
Reference in New Issue
Block a user