systemctl-enable: support reenable --now

Also, instead of silently continuing when template units
are specified with enable --now, print a warning and skip them.

Closes #31541
This commit is contained in:
Mike Yuan
2024-07-09 16:46:13 +02:00
parent 5ed6cc7ca9
commit 98aedce914
2 changed files with 51 additions and 19 deletions
+43 -14
View File
@@ -316,10 +316,26 @@ int verb_enable(int argc, char *argv[], void *userdata) {
if (arg_now) {
_cleanup_strv_free_ char **new_args = NULL;
const char *start_verb;
bool accept_path, prohibit_templates;
if (!STR_IN_SET(verb, "enable", "disable", "mask"))
if (streq(verb, "enable")) {
start_verb = "start";
accept_path = true;
prohibit_templates = true;
} else if (STR_IN_SET(verb, "disable", "mask")) {
start_verb = "stop";
accept_path = false;
prohibit_templates = false;
} else if (streq(verb, "reenable")) {
/* Note that we use try-restart here. This matches the semantics of reenable better,
* and allows us to glob template units. */
start_verb = "try-restart";
accept_path = true;
prohibit_templates = false;
} else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--now can only be used with verb enable, disable, or mask.");
"--now can only be used with verb enable, disable, reenable, or mask.");
if (install_client_side())
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
@@ -327,33 +343,46 @@ int verb_enable(int argc, char *argv[], void *userdata) {
assert(bus);
if (strv_extend(&new_args, streq(verb, "enable") ? "start" : "stop") < 0)
if (strv_extend(&new_args, start_verb) < 0)
return log_oom();
STRV_FOREACH(name, names) {
if (streq(verb, "enable")) {
char *fn;
_cleanup_free_ char *fn = NULL;
const char *unit_name;
/* 'enable' accept path to unit files, so extract it first. Don't try to
* glob them though, as starting globbed unit seldom makes sense and
* actually changes the semantic (we're operating on DefaultInstance=
* when enabling). */
if (accept_path) {
/* 'enable' and 'reenable' accept path to unit files, so extract it first. */
r = path_extract_filename(*name, &fn);
if (r < 0)
return log_error_errno(r, "Failed to extract filename of '%s': %m", *name);
r = strv_consume(&new_args, fn);
} else if (unit_name_is_valid(*name, UNIT_NAME_TEMPLATE)) {
unit_name = fn;
} else
unit_name = *name;
if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
char *globbed;
r = unit_name_replace_instance_full(*name, "*", /* accept_glob = */ true, &globbed);
if (prohibit_templates) {
/* Skip template units when enabling. Globbing doesn't make sense
* since the semantics would be altered (we're operating on
* DefaultInstance= when enabling), and starting template unit
* is not supported anyway. */
log_warning("Template unit is not supported by %s --now, skipping: %s",
verb, unit_name);
continue;
}
assert(!STR_IN_SET(start_verb, "start", "restart"));
r = unit_name_replace_instance_full(unit_name, "*", /* accept_glob = */ true, &globbed);
if (r < 0)
return log_error_errno(r, "Failed to glob unit name '%s': %m", *name);
return log_error_errno(r, "Failed to glob unit name '%s': %m", unit_name);
r = strv_consume(&new_args, globbed);
} else
r = strv_extend(&new_args, *name);
r = strv_extend(&new_args, unit_name);
if (r < 0)
return log_oom();
}