From: Gavin Li Date: Thu, 10 Oct 2024 20:07:16 +0000 (-0400) Subject: run: add --job-mode= argument X-Git-Tag: v258-rc1~1515^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F34708%2Fhead;p=thirdparty%2Fsystemd.git run: add --job-mode= argument systemctl has a --job-mode= argument, and adding the same argument to systemd-run is useful for starting transient scopes with dependencies. For example, if a transient scope BindsTo a service that is stopping, specifying --job-mode=replace will wait for the service to stop before starting it again, while the default job mode of "fail" will cause the systemd-run invocation to fail. --- diff --git a/man/systemd-run.xml b/man/systemd-run.xml index eeefe901dcf..a0924e30a26 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -484,6 +484,23 @@ + + + + + When queuing a new job, this option controls how to deal with + already queued jobs. + + The option takes the same mode values as + systemctl1's + option. The default job mode is fail. + + Running shows a list of available job modes. + + + + + diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run index 4537211ae55..4524744bb5f 100644 --- a/shell-completion/bash/systemd-run +++ b/shell-completion/bash/systemd-run @@ -38,7 +38,7 @@ _systemd_run() { --unit -p --property --slice --description --service-type --uid --gid --nice --working-directory -E --setenv --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar --path-property --socket-property --timer-property -H --host -M --machine --expand-environment - --background --json + --background --json --job-mode ) local OPTS="${opts_with_values[*]} --no-ask-password --scope -u --slice-inherit -r --remain-after-exit --send-sighup -d --same-dir -t --pty -P --pipe -S --shell -q --quiet --ignore-failure @@ -131,6 +131,11 @@ _systemd_run() { COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; + --job-mode) + local comps=$( systemd-run --job-mode=help 2>/dev/null ) + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; esac COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) diff --git a/shell-completion/zsh/_systemd-run b/shell-completion/zsh/_systemd-run index 4bb864da219..9ee58971780 100644 --- a/shell-completion/zsh/_systemd-run +++ b/shell-completion/zsh/_systemd-run @@ -22,6 +22,13 @@ __systemctl() { _describe 'slices' _slices } +(( $+functions[_systemd-run_job_modes] )) || + _systemd-run_job_modes() { + local -a _modes + _modes=($( systemd-run --job-mode=help 2>/dev/null )) + _values "${_modes[@]}" + } + _arguments \ '(-G --collect)'{-G,--collect}'[Unload the transient unit after it completed]' \ '--description=[Description for unit]:description' \ @@ -60,6 +67,7 @@ _arguments \ '(-t --pty)'{-t,--pty}'[The service connects to the terminal]' \ '(-q --quiet)'{-q,--quiet}'[Suppresses additional informational output]' \ '--json=[Output as JSON]:JSON:(pretty short off)' \ + '--job-mode=[Specify how to deal with other jobs]:mode:_systemd-run_job_modes' \ '(-r --remain-after-exit)'{-r,--remain-after-exit}'[Leave service around until explicitly stopped]' \ '(-d --same-dir)'{-d,--same-dir}'[Run on the current working directory]' \ '--scope[Run this as scope rather than service]' \ diff --git a/src/run/run.c b/src/run/run.c index af28d60858a..68966ccbda2 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -40,6 +40,7 @@ #include "ptyfwd.h" #include "signal-util.h" #include "special.h" +#include "string-table.h" #include "strv.h" #include "terminal-util.h" #include "uid-classification.h" @@ -82,6 +83,7 @@ static bool arg_quiet = false; static bool arg_aggressive_gc = false; static char *arg_working_directory = NULL; static bool arg_shell = false; +static JobMode arg_job_mode = JOB_FAIL; static char **arg_cmdline = NULL; static char *arg_exec_path = NULL; static bool arg_ignore_failure = false; @@ -143,6 +145,8 @@ static int help(void) { " --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" + " --job-mode=MODE Specify how to deal with already queued jobs,\n" + " when queueing a new job\n" " --ignore-failure Ignore the exit status of the invoked process\n" " --background=COLOR Set ANSI color for background\n" "\n%3$sPath options:%4$s\n" @@ -278,6 +282,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_WAIT, ARG_WORKING_DIRECTORY, ARG_SHELL, + ARG_JOB_MODE, ARG_IGNORE_FAILURE, ARG_BACKGROUND, ARG_JSON, @@ -327,6 +332,7 @@ static int parse_argv(int argc, char *argv[]) { { "working-directory", required_argument, NULL, ARG_WORKING_DIRECTORY }, { "same-dir", no_argument, NULL, 'd' }, { "shell", no_argument, NULL, 'S' }, + { "job-mode", required_argument, NULL, ARG_JOB_MODE }, { "ignore-failure", no_argument, NULL, ARG_IGNORE_FAILURE }, { "background", required_argument, NULL, ARG_BACKGROUND }, { "json", required_argument, NULL, ARG_JSON }, @@ -621,6 +627,17 @@ static int parse_argv(int argc, char *argv[]) { arg_shell = true; break; + case ARG_JOB_MODE: + if (streq(optarg, "help")) + return DUMP_STRING_TABLE(job_mode, JobMode, _JOB_MODE_MAX); + + r = job_mode_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Invalid job mode: %s", optarg); + + arg_job_mode = r; + break; + case ARG_IGNORE_FAILURE: arg_ignore_failure = true; break; @@ -1768,7 +1785,7 @@ static int make_transient_service_unit( return bus_log_create_error(r); /* Name and mode */ - r = sd_bus_message_append(m, "ss", service, "fail"); + r = sd_bus_message_append(m, "ss", service, job_mode_to_string(arg_job_mode)); if (r < 0) return bus_log_create_error(r); @@ -2283,7 +2300,7 @@ static int start_transient_scope(sd_bus *bus) { return bus_log_create_error(r); /* Name and Mode */ - r = sd_bus_message_append(m, "ss", scope, "fail"); + r = sd_bus_message_append(m, "ss", scope, job_mode_to_string(arg_job_mode)); if (r < 0) return bus_log_create_error(r); @@ -2452,7 +2469,7 @@ static int make_transient_trigger_unit( return bus_log_create_error(r); /* Name and Mode */ - r = sd_bus_message_append(m, "ss", trigger, "fail"); + r = sd_bus_message_append(m, "ss", trigger, job_mode_to_string(arg_job_mode)); if (r < 0) return bus_log_create_error(r); diff --git a/test/units/TEST-74-AUX-UTILS.run.sh b/test/units/TEST-74-AUX-UTILS.run.sh index d47550c8016..f624b00c89c 100755 --- a/test/units/TEST-74-AUX-UTILS.run.sh +++ b/test/units/TEST-74-AUX-UTILS.run.sh @@ -200,6 +200,16 @@ grep -q "^SocketMode=0644$" "/run/systemd/transient/$UNIT.socket" grep -qE "^ExecStart=.*/bin/true.*$" "/run/systemd/transient/$UNIT.service" systemctl stop "$UNIT.socket" "$UNIT.service" || : +: "Job mode" +systemd-run --job-mode=help +(! systemd-run --job-mode=foo --scope true) +systemd-run --no-block --unit=slowly-activating.service --collect \ + --service-type=oneshot --remain-after-exit \ + sleep 30 +(! systemd-run --scope --property=Conflicts=slowly-activating.service true) +(! systemd-run --scope --property=Conflicts=slowly-activating.service --job-mode=fail true) +systemd-run --scope --property=Conflicts=slowly-activating.service --job-mode=replace true + : "Interactive options" SHELL=/bin/true systemd-run --shell SHELL=/bin/true systemd-run --scope --shell