]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl-enable: support reenable --now 33559/head
authorMike Yuan <me@yhndnzj.com>
Thu, 29 Feb 2024 15:57:31 +0000 (23:57 +0800)
committerMike Yuan <me@yhndnzj.com>
Tue, 9 Jul 2024 14:46:13 +0000 (16:46 +0200)
Also, instead of silently continuing when template units
are specified with enable --now, print a warning and skip them.

Closes #31541

man/systemctl.xml
src/systemctl/systemctl-enable.c

index e589711ea8783f31f131fb34556d19c158630b84..55389a910bc6d2cad8cf6696dfefbd98bd5534a2 100644 (file)
@@ -973,6 +973,11 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
             enabled with to the defaults configured in its [Install] section. This command expects
             a unit name only, it does not accept paths to unit files.</para>
 
+            <para>This command implicitly reloads the system manager configuration after completing the operation.
+            Note that this command does not implicitly restart the units that are being disabled. If this is
+            desired, either combine this command with the <option>--now</option> switch, or invoke
+            the <command>try-restart</command> command with appropriate arguments later.</para>
+
             <xi:include href="version-info.xml" xpointer="v238"/>
           </listitem>
         </varlistentry>
@@ -2583,11 +2588,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         <term><option>--now</option></term>
 
         <listitem>
-          <para>When used with <command>enable</command>, the units
-          will also be started. When used with <command>disable</command> or
-          <command>mask</command>, the units will also be stopped. The start
-          or stop operation is only carried out when the respective enable or
-          disable operation has been successful.</para>
+          <para>When used with <command>enable</command>, <command>disable</command>, <command>mask</command>,
+          or <command>reenable</command>, also start/stop/try-restart the units after the specified
+          unit file operations succeed.</para>
 
           <xi:include href="version-info.xml" xpointer="v220"/>
         </listitem>
index c8211e80c79e47955f22e5e7e2a890980a01c551..ad907650298ef67fa8600e76dd5ccf22cc66ba72 100644 (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();
                 }