mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-09-09 17:45:00 +03:00
systemctl: add "reload-or-restart --marked"
This is almost equivalent to 'busctl call-method org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager EnqueueMarkedJobs', but waits for the jobs to finish.
This commit is contained in:
@@ -2316,6 +2316,18 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||||||
a directory, but a regular file, device node, socket or FIFO.</para></listitem>
|
a directory, but a regular file, device node, socket or FIFO.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--marked</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Only allowed with <command>reload-or-restart</command>. Enqueues restart jobs for all
|
||||||
|
units that have the <literal>needs-restart</literal> mark, and reload jobs for units that have the
|
||||||
|
<literal>needs-reload</literal> mark. When a unit marked for reload does not support reload, restart
|
||||||
|
will be queued. Those properties can be set using <command>set-property Marks</command>.</para>
|
||||||
|
|
||||||
|
<para>Unless <option>--no-block</option> is used, <command>systemctl</command> will wait for the
|
||||||
|
queued jobs to finish.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--read-only</option></term>
|
<term><option>--read-only</option></term>
|
||||||
|
|
||||||
|
@@ -176,6 +176,43 @@ fail:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int enqueue_marked_jobs(
|
||||||
|
sd_bus *bus,
|
||||||
|
BusWaitForJobs *w) {
|
||||||
|
|
||||||
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||||
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
log_debug("%s dbus call org.freedesktop.systemd1.Manager EnqueueMarkedJobs()",
|
||||||
|
arg_dry_run ? "Would execute" : "Executing");
|
||||||
|
|
||||||
|
if (arg_dry_run)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = bus_call_method(bus, bus_systemd_mgr, "EnqueueMarkedJobs", &error, &reply, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to start jobs: %s", bus_error_message(&error, r));
|
||||||
|
|
||||||
|
_cleanup_strv_free_ char **paths = NULL;
|
||||||
|
r = sd_bus_message_read_strv(reply, &paths);
|
||||||
|
if (r < 0)
|
||||||
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
|
if (w) {
|
||||||
|
char **path;
|
||||||
|
|
||||||
|
STRV_FOREACH(path, paths) {
|
||||||
|
log_debug("Adding %s to the set", *path);
|
||||||
|
r = bus_wait_for_jobs_add(w, *path);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to watch job %s: %m", *path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const struct action_metadata action_table[_ACTION_MAX] = {
|
const struct action_metadata action_table[_ACTION_MAX] = {
|
||||||
[ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
|
[ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
|
||||||
[ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
|
[ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
|
||||||
@@ -265,7 +302,7 @@ int start_unit(int argc, char *argv[], void *userdata) {
|
|||||||
job_type = "start";
|
job_type = "start";
|
||||||
mode = "isolate";
|
mode = "isolate";
|
||||||
suffix = ".target";
|
suffix = ".target";
|
||||||
} else {
|
} else if (!arg_marked) {
|
||||||
/* A command in style of "systemctl start <unit1> <unit2> …", "sysemctl stop <unit1> <unit2> …" and so on */
|
/* A command in style of "systemctl start <unit1> <unit2> …", "sysemctl stop <unit1> <unit2> …" and so on */
|
||||||
method = verb_to_method(argv[0]);
|
method = verb_to_method(argv[0]);
|
||||||
job_type = verb_to_job_type(argv[0]);
|
job_type = verb_to_job_type(argv[0]);
|
||||||
@@ -289,7 +326,7 @@ int start_unit(int argc, char *argv[], void *userdata) {
|
|||||||
names = strv_new(one_name);
|
names = strv_new(one_name);
|
||||||
if (!names)
|
if (!names)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
} else {
|
} else if (!arg_marked) {
|
||||||
bool expanded;
|
bool expanded;
|
||||||
|
|
||||||
r = expand_unit_names(bus, strv_skip(argv, 1), suffix, &names, &expanded);
|
r = expand_unit_names(bus, strv_skip(argv, 1), suffix, &names, &expanded);
|
||||||
@@ -322,19 +359,23 @@ int start_unit(int argc, char *argv[], void *userdata) {
|
|||||||
return log_error_errno(r, "Failed to allocate unit watch context: %m");
|
return log_error_errno(r, "Failed to allocate unit watch context: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(name, names) {
|
if (arg_marked)
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
ret = enqueue_marked_jobs(bus, w);
|
||||||
|
|
||||||
r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu);
|
else
|
||||||
if (ret == EXIT_SUCCESS && r < 0)
|
STRV_FOREACH(name, names) {
|
||||||
ret = translate_bus_error_to_exit_status(r, &error);
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
|
||||||
if (r >= 0 && streq(method, "StopUnit")) {
|
r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu);
|
||||||
r = strv_push(&stopped_units, *name);
|
if (ret == EXIT_SUCCESS && r < 0)
|
||||||
if (r < 0)
|
ret = translate_bus_error_to_exit_status(r, &error);
|
||||||
return log_oom();
|
|
||||||
|
if (r >= 0 && streq(method, "StopUnit")) {
|
||||||
|
r = strv_push(&stopped_units, *name);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!arg_no_block) {
|
if (!arg_no_block) {
|
||||||
const char* extra_args[4];
|
const char* extra_args[4];
|
||||||
|
@@ -108,6 +108,7 @@ char **arg_clean_what = NULL;
|
|||||||
TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
|
TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
|
||||||
bool arg_read_only = false;
|
bool arg_read_only = false;
|
||||||
bool arg_mkdir = false;
|
bool arg_mkdir = false;
|
||||||
|
bool arg_marked = false;
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||||
@@ -295,6 +296,7 @@ static int systemctl_help(void) {
|
|||||||
" 'us+utc': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC\n"
|
" 'us+utc': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC\n"
|
||||||
" --read-only Create read-only bind mount\n"
|
" --read-only Create read-only bind mount\n"
|
||||||
" --mkdir Create directory before mounting, if missing\n"
|
" --mkdir Create directory before mounting, if missing\n"
|
||||||
|
" --marked Restart/reload previously marked units\n"
|
||||||
"\nSee the %2$s for details.\n",
|
"\nSee the %2$s for details.\n",
|
||||||
program_invocation_short_name,
|
program_invocation_short_name,
|
||||||
link,
|
link,
|
||||||
@@ -413,6 +415,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||||||
ARG_TIMESTAMP_STYLE,
|
ARG_TIMESTAMP_STYLE,
|
||||||
ARG_READ_ONLY,
|
ARG_READ_ONLY,
|
||||||
ARG_MKDIR,
|
ARG_MKDIR,
|
||||||
|
ARG_MARKED,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
@@ -471,6 +474,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||||||
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP_STYLE },
|
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP_STYLE },
|
||||||
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
|
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
|
||||||
{ "mkdir", no_argument, NULL, ARG_MKDIR },
|
{ "mkdir", no_argument, NULL, ARG_MKDIR },
|
||||||
|
{ "marked", no_argument, NULL, ARG_MARKED },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -900,6 +904,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||||||
arg_mkdir = true;
|
arg_mkdir = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_MARKED:
|
||||||
|
arg_marked = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
/* Output an error mimicking getopt, and print a hint afterwards */
|
/* Output an error mimicking getopt, and print a hint afterwards */
|
||||||
log_error("%s: invalid option -- '.'", program_invocation_name);
|
log_error("%s: invalid option -- '.'", program_invocation_name);
|
||||||
@@ -923,6 +931,27 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"--wait may not be combined with --no-block.");
|
"--wait may not be combined with --no-block.");
|
||||||
|
|
||||||
|
bool do_reload_or_restart = streq_ptr(argv[optind], "reload-or-restart");
|
||||||
|
if (arg_marked) {
|
||||||
|
if (!do_reload_or_restart)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"--marked may only be used with 'reload-or-restart'.");
|
||||||
|
if (optind + 1 < argc)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"No additional arguments allowed with 'reload-or-restart --marked'.");
|
||||||
|
if (arg_wait)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"--marked --wait is not supported.");
|
||||||
|
if (arg_show_transaction)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"--marked --show-transaction is not supported.");
|
||||||
|
|
||||||
|
} else if (do_reload_or_restart) {
|
||||||
|
if (optind + 1 >= argc)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"List of units to restart/reload is required.");
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1004,7 +1033,7 @@ static int systemctl_main(int argc, char *argv[]) {
|
|||||||
{ "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
{ "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
||||||
{ "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
{ "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
||||||
{ "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
{ "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
||||||
{ "reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
{ "reload-or-restart", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
||||||
{ "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with old systemctl <= 228 */
|
{ "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with old systemctl <= 228 */
|
||||||
{ "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
{ "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
|
||||||
{ "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */
|
{ "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */
|
||||||
|
@@ -93,5 +93,6 @@ extern char **arg_clean_what;
|
|||||||
extern TimestampStyle arg_timestamp_style;
|
extern TimestampStyle arg_timestamp_style;
|
||||||
extern bool arg_read_only;
|
extern bool arg_read_only;
|
||||||
extern bool arg_mkdir;
|
extern bool arg_mkdir;
|
||||||
|
extern bool arg_marked;
|
||||||
|
|
||||||
int systemctl_dispatch_parse_argv(int argc, char *argv[]);
|
int systemctl_dispatch_parse_argv(int argc, char *argv[]);
|
||||||
|
Reference in New Issue
Block a user