mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
systemctl: add --kill-subgroup= switch for killing subcgroup
This commit is contained in:
@@ -2494,11 +2494,12 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
one is then considered the main process of the unit (if it can be determined). This is different
|
||||
for service units of other types, where the process forked off by the manager for
|
||||
<varname>ExecStart=</varname> is always the main process itself. A service unit consists of zero or
|
||||
one main process, zero or one control process plus any number of additional processes. Not all unit
|
||||
types manage processes of these types however. For example, for mount units, control processes are
|
||||
defined (which are the invocations of <filename>&MOUNT_PATH;</filename> and
|
||||
<filename>&UMOUNT_PATH;</filename>), but no main process is defined. If omitted, defaults to
|
||||
<option>all</option>.</para>
|
||||
one main process, zero or one control process plus any number of additional processes part of the
|
||||
unit's control group. Not all unit types manage processes of these types however. For example, for
|
||||
mount units, control processes are defined (which are the invocations of
|
||||
<filename>&MOUNT_PATH;</filename> and <filename>&UMOUNT_PATH;</filename>), but no main process is
|
||||
defined. If omitted, defaults to <option>all</option>, except if <option>--kill-subgroup=</option>
|
||||
is used in which case defaults to <option>cgroup</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v252"/>
|
||||
</listitem>
|
||||
@@ -2525,6 +2526,28 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--kill-subgroup=<replaceable>PATH</replaceable></option></term>
|
||||
|
||||
<listitem><para>Takes a control group sub-path to send signals to, for use with the
|
||||
<command>kill</command> command. By default the chosen signal is delivered to all processes of the
|
||||
unit's cgroups (as well as the main/control processes (if outside) – subject to
|
||||
<option>--kill-whom=</option>). But with this option a subgroup can be selelected instead. This
|
||||
functionality is only available if <literal>cgroup</literal> or <literal>cgroup-fail</literal> are
|
||||
used with <option>--kill-whom=</option>, and in fact the former is the default if
|
||||
<option>--kill-subgroup=</option> is used.</para>
|
||||
|
||||
<para>The specified path may, but doesn't have to be prefixed with a slash, and its absence or
|
||||
presence has no effect, the path is either way taken relative to the unit's main control group
|
||||
path.</para>
|
||||
|
||||
<para>This functionality is only available on units where control group delegation is enabled (see
|
||||
<varname>Delegate=</varname> in
|
||||
<member><citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>).</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="signal" />
|
||||
|
||||
<varlistentry>
|
||||
|
||||
@@ -20,6 +20,9 @@ int verb_kill(int argc, char *argv[], void *userdata) {
|
||||
sd_bus *bus;
|
||||
int r, q;
|
||||
|
||||
if (arg_kill_subgroup && arg_kill_value_set)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--kill-subgroup= and --kill-value= may not be combined.");
|
||||
|
||||
r = acquire_bus(BUS_MANAGER, &bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -32,7 +35,7 @@ int verb_kill(int argc, char *argv[], void *userdata) {
|
||||
|
||||
polkit_agent_open_maybe();
|
||||
|
||||
kill_whom = arg_kill_whom ?: "all";
|
||||
kill_whom = arg_kill_whom ?: arg_kill_subgroup ? "cgroup" : "all";
|
||||
|
||||
/* --fail was specified */
|
||||
if (streq(arg_job_mode(), "fail"))
|
||||
@@ -53,6 +56,14 @@ int verb_kill(int argc, char *argv[], void *userdata) {
|
||||
&error,
|
||||
NULL,
|
||||
"ssii", *name, kill_whom, arg_signal, arg_kill_value);
|
||||
else if (arg_kill_subgroup)
|
||||
q = bus_call_method(
|
||||
bus,
|
||||
bus_systemd_mgr,
|
||||
"KillUnitSubgroup",
|
||||
&error,
|
||||
NULL,
|
||||
"sssi", *name, kill_whom, arg_kill_subgroup, arg_signal);
|
||||
else
|
||||
q = bus_call_method(
|
||||
bus,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "static-destruct.h"
|
||||
#include "string-table.h"
|
||||
@@ -88,6 +89,7 @@ bool arg_mkdir = false;
|
||||
bool arg_marked = false;
|
||||
const char *arg_drop_in = NULL;
|
||||
ImagePolicy *arg_image_policy = NULL;
|
||||
char *arg_kill_subgroup = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
|
||||
@@ -103,6 +105,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_drop_in, unsetp);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_kill_subgroup, freep);
|
||||
|
||||
static int systemctl_help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
@@ -253,9 +256,11 @@ static int systemctl_help(void) {
|
||||
" Whether to check inhibitors before shutting down,\n"
|
||||
" sleeping, or hibernating\n"
|
||||
" -i Shortcut for --check-inhibitors=no\n"
|
||||
" -s --signal=SIGNAL Which signal to send\n"
|
||||
" --kill-whom=WHOM Whom to send signal to\n"
|
||||
" --kill-value=INT Signal value to enqueue\n"
|
||||
" -s --signal=SIGNAL Which signal to send\n"
|
||||
" --kill-subgroup=PATH\n"
|
||||
" Send signal to sub-control-group only\n"
|
||||
" --what=RESOURCES Which types of resources to remove\n"
|
||||
" --now Start or stop unit after enabling or disabling it\n"
|
||||
" --dry-run Only print what would be done\n"
|
||||
@@ -438,6 +443,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
ARG_DROP_IN,
|
||||
ARG_WHEN,
|
||||
ARG_STDIN,
|
||||
ARG_KILL_SUBGROUP,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -507,6 +513,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
{ "drop-in", required_argument, NULL, ARG_DROP_IN },
|
||||
{ "when", required_argument, NULL, ARG_WHEN },
|
||||
{ "stdin", no_argument, NULL, ARG_STDIN },
|
||||
{ "kill-subgroup", required_argument, NULL, ARG_KILL_SUBGROUP },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1021,6 +1028,23 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
arg_stdin = true;
|
||||
break;
|
||||
|
||||
case ARG_KILL_SUBGROUP: {
|
||||
if (empty_or_root(optarg)) {
|
||||
arg_kill_subgroup = mfree(arg_kill_subgroup);
|
||||
break;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *p = NULL;
|
||||
if (path_simplify_alloc(optarg, &p) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (!path_is_safe(p))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Control group sub-path '%s' is not valid.", p);
|
||||
|
||||
free_and_replace(arg_kill_subgroup, p);
|
||||
break;
|
||||
}
|
||||
|
||||
case '.':
|
||||
/* Output an error mimicking getopt, and print a hint afterwards */
|
||||
log_error("%s: invalid option -- '.'", program_invocation_name);
|
||||
|
||||
@@ -100,6 +100,7 @@ extern bool arg_mkdir;
|
||||
extern bool arg_marked;
|
||||
extern const char *arg_drop_in;
|
||||
extern ImagePolicy *arg_image_policy;
|
||||
extern char *arg_kill_subgroup;
|
||||
|
||||
static inline const char* arg_job_mode(void) {
|
||||
return _arg_job_mode ?: "replace";
|
||||
|
||||
Reference in New Issue
Block a user