You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
18 KiB
457 lines
18 KiB
From 65d36d59c936650e141fcbf38b287627fd0ba21a Mon Sep 17 00:00:00 2001 |
|
From: Jan Synacek <jsynacek@redhat.com> |
|
Date: Fri, 15 May 2015 09:54:10 +0200 |
|
Subject: [PATCH] systemctl: introduce --now for enable, disable and mask |
|
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=42940 |
|
|
|
Conflicts: |
|
src/libsystemd/sd-bus/bus-util.c |
|
src/libsystemd/sd-bus/bus-util.h |
|
src/systemctl/systemctl.c |
|
|
|
Cherry-picked from: 57ab2eabb8f92fad5239c7d4492e9c6e23ee0678 |
|
Resolves: #1233081 |
|
--- |
|
Makefile.am | 1 + |
|
man/systemctl.xml | 33 ++++++--- |
|
src/libsystemd/sd-bus/bus-util.c | 6 +- |
|
src/libsystemd/sd-bus/bus-util.h | 3 +- |
|
src/machine/machinectl.c | 2 +- |
|
src/shared/install.c | 112 +++++++++++++++---------------- |
|
src/shared/install.h | 1 + |
|
src/systemctl/systemctl.c | 28 ++++++-- |
|
8 files changed, 114 insertions(+), 72 deletions(-) |
|
|
|
diff --git a/Makefile.am b/Makefile.am |
|
index 604eaf2f17..d3fb398fe5 100644 |
|
--- a/Makefile.am |
|
+++ b/Makefile.am |
|
@@ -5253,6 +5253,7 @@ machinectl_LDADD = \ |
|
libsystemd-internal.la \ |
|
libsystemd-logs.la \ |
|
libsystemd-journal-internal.la \ |
|
+ libsystemd-units.la \ |
|
libsystemd-shared.la |
|
|
|
rootbin_PROGRAMS += \ |
|
diff --git a/man/systemctl.xml b/man/systemctl.xml |
|
index 3c4c9cb92c..44ec0d7bcf 100644 |
|
--- a/man/systemctl.xml |
|
+++ b/man/systemctl.xml |
|
@@ -455,6 +455,18 @@ |
|
</listitem> |
|
</varlistentry> |
|
|
|
+ <varlistentry> |
|
+ <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> |
|
+ </listitem> |
|
+ </varlistentry> |
|
+ |
|
<varlistentry> |
|
<term><option>--root=</option></term> |
|
|
|
@@ -909,11 +921,12 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service |
|
the changes are taken into account immediately. Note that |
|
this does <emphasis>not</emphasis> have the effect of also |
|
starting any of the units being enabled. If this |
|
- is desired, a separate <command>start</command> command must |
|
- be invoked for the unit. Also note that in case of instance |
|
- enablement, symlinks named the same as instances are created in |
|
- the install location, however they all point to the same |
|
- template unit file.</para> |
|
+ is desired, either <option>--now</option> should be used |
|
+ together with this command, or an additional <command>start</command> |
|
+ command must be invoked for the unit. Also note that in case of |
|
+ instance enablement, symlinks named the same as instances |
|
+ are created in the install location, however they all point to the |
|
+ same template unit file.</para> |
|
|
|
<para>This command will print the actions executed. This |
|
output may be suppressed by passing <option>--quiet</option>. |
|
@@ -968,9 +981,10 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service |
|
<command>enable</command>. This call implicitly reloads the |
|
systemd daemon configuration after completing the disabling |
|
of the units. Note that this command does not implicitly |
|
- stop the units that are being disabled. If this is desired, |
|
- an additional <command>stop</command> command should be |
|
- executed afterwards.</para> |
|
+ stop the units that are being disabled. If this is desired, either |
|
+ <option>--now</option> should be used together with this command, or |
|
+ an additional <command>stop</command> command should be executed |
|
+ afterwards.</para> |
|
|
|
<para>This command will print the actions executed. This |
|
output may be suppressed by passing <option>--quiet</option>. |
|
@@ -1116,7 +1130,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service |
|
activation of the unit, including enablement and manual |
|
activation. Use this option with care. This honors the |
|
<option>--runtime</option> option to only mask temporarily |
|
- until the next reboot of the system.</para> |
|
+ until the next reboot of the system. The <option>--now</option> |
|
+ option can be used to ensure that the units are also stopped.</para> |
|
</listitem> |
|
</varlistentry> |
|
|
|
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c |
|
index 2e6d889620..fff00d9f93 100644 |
|
--- a/src/libsystemd/sd-bus/bus-util.c |
|
+++ b/src/libsystemd/sd-bus/bus-util.c |
|
@@ -1849,7 +1849,7 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { |
|
return set_put_strdup(d->jobs, path); |
|
} |
|
|
|
-int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { |
|
+int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { |
|
const char *type, *path, *source; |
|
int r; |
|
|
|
@@ -1864,6 +1864,10 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { |
|
else |
|
log_info("Removed symlink %s.", path); |
|
} |
|
+ |
|
+ r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source); |
|
+ if (r < 0) |
|
+ return r; |
|
} |
|
if (r < 0) |
|
return bus_log_parse_error(r); |
|
diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h |
|
index e8a97cef9e..21db982280 100644 |
|
--- a/src/libsystemd/sd-bus/bus-util.h |
|
+++ b/src/libsystemd/sd-bus/bus-util.h |
|
@@ -24,6 +24,7 @@ |
|
#include "sd-event.h" |
|
#include "sd-bus.h" |
|
#include "hashmap.h" |
|
+#include "install.h" |
|
#include "time-util.h" |
|
#include "util.h" |
|
|
|
@@ -211,4 +212,4 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet); |
|
|
|
DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); |
|
|
|
-int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet); |
|
+int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes); |
|
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c |
|
index 9f8c68b184..f1910709d2 100644 |
|
--- a/src/machine/machinectl.c |
|
+++ b/src/machine/machinectl.c |
|
@@ -1709,7 +1709,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) { |
|
return bus_log_parse_error(r); |
|
} |
|
|
|
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); |
|
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); |
|
if (r < 0) |
|
return r; |
|
|
|
diff --git a/src/shared/install.c b/src/shared/install.c |
|
index efd489ec08..b62065be5c 100644 |
|
--- a/src/shared/install.c |
|
+++ b/src/shared/install.c |
|
@@ -113,51 +113,6 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d |
|
return 0; |
|
} |
|
|
|
-static int add_file_change( |
|
- UnitFileChange **changes, |
|
- unsigned *n_changes, |
|
- UnitFileChangeType type, |
|
- const char *path, |
|
- const char *source) { |
|
- |
|
- UnitFileChange *c; |
|
- unsigned i; |
|
- |
|
- assert(path); |
|
- assert(!changes == !n_changes); |
|
- |
|
- if (!changes) |
|
- return 0; |
|
- |
|
- c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange)); |
|
- if (!c) |
|
- return -ENOMEM; |
|
- |
|
- *changes = c; |
|
- i = *n_changes; |
|
- |
|
- c[i].type = type; |
|
- c[i].path = strdup(path); |
|
- if (!c[i].path) |
|
- return -ENOMEM; |
|
- |
|
- path_kill_slashes(c[i].path); |
|
- |
|
- if (source) { |
|
- c[i].source = strdup(source); |
|
- if (!c[i].source) { |
|
- free(c[i].path); |
|
- return -ENOMEM; |
|
- } |
|
- |
|
- path_kill_slashes(c[i].path); |
|
- } else |
|
- c[i].source = NULL; |
|
- |
|
- *n_changes = i+1; |
|
- return 0; |
|
-} |
|
- |
|
static int mark_symlink_for_removal( |
|
Set **remove_symlinks_to, |
|
const char *p) { |
|
@@ -310,7 +265,7 @@ static int remove_marked_symlinks_fd( |
|
|
|
path_kill_slashes(p); |
|
rmdir_parents(p, config_path); |
|
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); |
|
|
|
if (!set_get(remove_symlinks_to, p)) { |
|
|
|
@@ -597,7 +552,7 @@ int unit_file_mask( |
|
} |
|
|
|
if (symlink("/dev/null", path) >= 0) { |
|
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); |
|
continue; |
|
} |
|
|
|
@@ -608,8 +563,8 @@ int unit_file_mask( |
|
|
|
if (force) { |
|
if (symlink_atomic("/dev/null", path) >= 0) { |
|
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); |
|
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); |
|
continue; |
|
} |
|
} |
|
@@ -665,7 +620,7 @@ int unit_file_unmask( |
|
q = -errno; |
|
else { |
|
q = mark_symlink_for_removal(&remove_symlinks_to, path); |
|
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); |
|
} |
|
} |
|
|
|
@@ -747,7 +702,7 @@ int unit_file_link( |
|
return -ENOMEM; |
|
|
|
if (symlink(*i, path) >= 0) { |
|
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); |
|
continue; |
|
} |
|
|
|
@@ -766,8 +721,8 @@ int unit_file_link( |
|
|
|
if (force) { |
|
if (symlink_atomic(*i, path) >= 0) { |
|
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); |
|
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); |
|
continue; |
|
} |
|
} |
|
@@ -794,6 +749,51 @@ void unit_file_list_free(Hashmap *h) { |
|
hashmap_free(h); |
|
} |
|
|
|
+int unit_file_changes_add( |
|
+ UnitFileChange **changes, |
|
+ unsigned *n_changes, |
|
+ UnitFileChangeType type, |
|
+ const char *path, |
|
+ const char *source) { |
|
+ |
|
+ UnitFileChange *c; |
|
+ unsigned i; |
|
+ |
|
+ assert(path); |
|
+ assert(!changes == !n_changes); |
|
+ |
|
+ if (!changes) |
|
+ return 0; |
|
+ |
|
+ c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange)); |
|
+ if (!c) |
|
+ return -ENOMEM; |
|
+ |
|
+ *changes = c; |
|
+ i = *n_changes; |
|
+ |
|
+ c[i].type = type; |
|
+ c[i].path = strdup(path); |
|
+ if (!c[i].path) |
|
+ return -ENOMEM; |
|
+ |
|
+ path_kill_slashes(c[i].path); |
|
+ |
|
+ if (source) { |
|
+ c[i].source = strdup(source); |
|
+ if (!c[i].source) { |
|
+ free(c[i].path); |
|
+ return -ENOMEM; |
|
+ } |
|
+ |
|
+ path_kill_slashes(c[i].path); |
|
+ } else |
|
+ c[i].source = NULL; |
|
+ |
|
+ *n_changes = i+1; |
|
+ return 0; |
|
+} |
|
+ |
|
void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) { |
|
unsigned i; |
|
|
|
@@ -1199,7 +1199,7 @@ static int create_symlink( |
|
mkdir_parents_label(new_path, 0755); |
|
|
|
if (symlink(old_path, new_path) >= 0) { |
|
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); |
|
return 0; |
|
} |
|
|
|
@@ -1220,8 +1220,8 @@ static int create_symlink( |
|
if (r < 0) |
|
return r; |
|
|
|
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); |
|
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); |
|
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); |
|
|
|
return 0; |
|
} |
|
diff --git a/src/shared/install.h b/src/shared/install.h |
|
index 3ca39397e6..d729e6ed15 100644 |
|
--- a/src/shared/install.h |
|
+++ b/src/shared/install.h |
|
@@ -112,6 +112,7 @@ UnitFileState unit_file_get_state( |
|
int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h); |
|
|
|
void unit_file_list_free(Hashmap *h); |
|
+int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source); |
|
void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes); |
|
|
|
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name); |
|
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c |
|
index 089c25f83f..9898694d75 100644 |
|
--- a/src/systemctl/systemctl.c |
|
+++ b/src/systemctl/systemctl.c |
|
@@ -138,6 +138,7 @@ static char *arg_host = NULL; |
|
static unsigned arg_lines = 10; |
|
static OutputMode arg_output = OUTPUT_SHORT; |
|
static bool arg_plain = false; |
|
+static bool arg_now = false; |
|
|
|
static bool original_stdout_is_tty; |
|
|
|
@@ -1979,7 +1980,7 @@ static int set_default(sd_bus *bus, char **args) { |
|
return r; |
|
} |
|
|
|
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); |
|
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); |
|
if (r < 0) |
|
return r; |
|
|
|
@@ -5415,7 +5416,7 @@ static int enable_unit(sd_bus *bus, char **args) { |
|
return bus_log_parse_error(r); |
|
} |
|
|
|
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); |
|
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); |
|
if (r < 0) |
|
return r; |
|
|
|
@@ -5437,6 +5438,18 @@ static int enable_unit(sd_bus *bus, char **args) { |
|
"3) A unit may be started when needed via activation (socket, path, timer,\n" |
|
" D-Bus, udev, scripted systemctl call, ...).\n"); |
|
|
|
+ if (arg_now && n_changes > 0 && STR_IN_SET(args[0], "enable", "disable", "mask")) { |
|
+ char *new_args[n_changes + 2]; |
|
+ unsigned i; |
|
+ |
|
+ new_args[0] = streq(args[0], "enable") ? (char *)"start" : (char *)"stop"; |
|
+ for (i = 0; i < n_changes; i++) |
|
+ new_args[i + 1] = basename(changes[i].path); |
|
+ new_args[i + 1] = NULL; |
|
+ |
|
+ r = start_unit(bus, new_args); |
|
+ } |
|
+ |
|
finish: |
|
unit_file_changes_free(changes, n_changes); |
|
|
|
@@ -5516,7 +5529,7 @@ static int add_dependency(sd_bus *bus, char **args) { |
|
return r; |
|
} |
|
|
|
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); |
|
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); |
|
if (r < 0) |
|
return r; |
|
|
|
@@ -5582,7 +5595,7 @@ static int preset_all(sd_bus *bus, char **args) { |
|
return r; |
|
} |
|
|
|
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); |
|
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); |
|
if (r < 0) |
|
return r; |
|
|
|
@@ -6058,6 +6071,7 @@ static void systemctl_help(void) { |
|
" When shutting down or sleeping, ignore inhibitors\n" |
|
" --kill-who=WHO Who to send signal to\n" |
|
" -s --signal=SIGNAL Which signal to send\n" |
|
+ " --now Start or stop unit in addition to enabling or disabling it\n" |
|
" -q --quiet Suppress output\n" |
|
" --no-block Do not wait until operation finished\n" |
|
" --no-wall Don't send wall message before halt/power-off/reboot\n" |
|
@@ -6255,6 +6269,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { |
|
ARG_STATE, |
|
ARG_JOB_MODE, |
|
ARG_PRESET_MODE, |
|
+ ARG_NOW, |
|
}; |
|
|
|
static const struct option options[] = { |
|
@@ -6297,6 +6312,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { |
|
{ "state", required_argument, NULL, ARG_STATE }, |
|
{ "recursive", no_argument, NULL, 'r' }, |
|
{ "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, |
|
+ { "now", no_argument, NULL, ARG_NOW }, |
|
{} |
|
}; |
|
|
|
@@ -6573,6 +6589,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { |
|
|
|
break; |
|
|
|
+ case ARG_NOW: |
|
+ arg_now = true; |
|
+ break; |
|
+ |
|
case '?': |
|
return -EINVAL; |
|
|
|
|