mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
systemctl: add new "clean" operation to systemctl
This exposes the CleanUnit() bus calls in systemctl, i.e. makes all the infrastructure we previously added useful to people.
This commit is contained in:
parent
3572d3df8f
commit
d81bc51fe3
@ -28,6 +28,7 @@
|
||||
#include "bus-unit-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "bus-wait-for-jobs.h"
|
||||
#include "bus-wait-for-units.h"
|
||||
#include "cgroup-show.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "copy.h"
|
||||
@ -162,12 +163,14 @@ static const char *arg_boot_loader_entry = NULL;
|
||||
static bool arg_now = false;
|
||||
static bool arg_jobs_before = false;
|
||||
static bool arg_jobs_after = false;
|
||||
static char **arg_clean_what = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
|
||||
|
||||
static int daemon_reload(int argc, char *argv[], void* userdata);
|
||||
static int trivial_method(int argc, char *argv[], void *userdata);
|
||||
@ -3951,6 +3954,101 @@ static int kill_unit(int argc, char *argv[], void *userdata) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int clean_unit(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(bus_wait_for_units_freep) BusWaitForUnits *w = NULL;
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
int r, ret = EXIT_SUCCESS;
|
||||
char **name;
|
||||
sd_bus *bus;
|
||||
|
||||
r = acquire_bus(BUS_FULL, &bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
polkit_agent_open_maybe();
|
||||
|
||||
if (!arg_clean_what) {
|
||||
arg_clean_what = strv_new("cache", "runtime");
|
||||
if (!arg_clean_what)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to expand names: %m");
|
||||
|
||||
if (!arg_no_block) {
|
||||
r = bus_wait_for_units_new(bus, &w);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate unit waiter: %m");
|
||||
}
|
||||
|
||||
STRV_FOREACH(name, names) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
|
||||
if (w) {
|
||||
/* If we shall wait for the cleaning to complete, let's add a ref on the unit first */
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"RefUnit",
|
||||
&error,
|
||||
NULL,
|
||||
"s", *name);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to add reference to unit %s: %s", *name, bus_error_message(&error, r));
|
||||
if (ret == EXIT_SUCCESS)
|
||||
ret = r;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
&m,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"CleanUnit");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "s", *name);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append_strv(m, arg_clean_what);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, NULL);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to clean unit %s: %s", *name, bus_error_message(&error, r));
|
||||
if (ret == EXIT_SUCCESS) {
|
||||
ret = r;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (w) {
|
||||
r = bus_wait_for_units_add_unit(w, *name, BUS_WAIT_REFFED|BUS_WAIT_FOR_MAINTENANCE_END, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to watch unit %s: %m", *name);
|
||||
}
|
||||
}
|
||||
|
||||
r = bus_wait_for_units_run(w);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to wait for units: %m");
|
||||
if (r == BUS_WAIT_FAILURE)
|
||||
ret = EXIT_FAILURE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct ExecStatusInfo {
|
||||
char *name;
|
||||
|
||||
@ -7712,6 +7810,7 @@ static int 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"
|
||||
" --what=RESOURCES Which types of resources to remove\n"
|
||||
" --now Start or stop unit in addition to enabling or disabling it\n"
|
||||
" --dry-run Only print what would be done\n"
|
||||
" -q --quiet Suppress output\n"
|
||||
@ -7760,6 +7859,8 @@ static int systemctl_help(void) {
|
||||
" if supported, otherwise restart\n"
|
||||
" isolate UNIT Start one unit and stop all others\n"
|
||||
" kill UNIT... Send signal to processes of a unit\n"
|
||||
" clean UNIT... Clean runtime, cache, state, logs or\n"
|
||||
" or configuration of unit\n"
|
||||
" is-active PATTERN... Check whether units are active\n"
|
||||
" is-failed PATTERN... Check whether units are failed\n"
|
||||
" status [PATTERN...|PID...] Show runtime status of one or more units\n"
|
||||
@ -8063,6 +8164,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
ARG_NOW,
|
||||
ARG_MESSAGE,
|
||||
ARG_WAIT,
|
||||
ARG_WHAT,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -8114,6 +8216,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
{ "now", no_argument, NULL, ARG_NOW },
|
||||
{ "message", required_argument, NULL, ARG_MESSAGE },
|
||||
{ "show-transaction", no_argument, NULL, 'T' },
|
||||
{ "what", required_argument, NULL, ARG_WHAT },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -8466,6 +8569,38 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
arg_show_transaction = true;
|
||||
break;
|
||||
|
||||
case ARG_WHAT: {
|
||||
const char *p;
|
||||
|
||||
if (isempty(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments.");
|
||||
|
||||
for (p = optarg;;) {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
r = extract_first_word(&p, &k, ",", 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse directory type: %s", optarg);
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(k, "help")) {
|
||||
puts("runtime\n"
|
||||
"state\n"
|
||||
"cache\n"
|
||||
"logs\n"
|
||||
"configuration");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = strv_consume(&arg_clean_what, TAKE_PTR(k));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '.':
|
||||
/* Output an error mimicking getopt, and print a hint afterwards */
|
||||
log_error("%s: invalid option -- '.'", program_invocation_name);
|
||||
@ -8912,6 +9047,7 @@ static int systemctl_main(int argc, char *argv[]) {
|
||||
{ "condrestart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with RH */
|
||||
{ "isolate", 2, 2, VERB_ONLINE_ONLY, start_unit },
|
||||
{ "kill", 2, VERB_ANY, VERB_ONLINE_ONLY, kill_unit },
|
||||
{ "clean", 2, VERB_ANY, VERB_ONLINE_ONLY, clean_unit },
|
||||
{ "is-active", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active },
|
||||
{ "check", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, /* deprecated alias of is-active */
|
||||
{ "is-failed", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_failed },
|
||||
|
Loading…
Reference in New Issue
Block a user