summaryrefslogtreecommitdiff
path: root/src/grp-system/systemctl
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-09-14 18:33:57 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-09-14 18:33:57 -0400
commit3c72c8d3ee67388336aca58c5afa3fb93a9c24c0 (patch)
treed072df7fee0f5906fad88c08398b2fe887cbc064 /src/grp-system/systemctl
parente51613a3291342c6006edda8783755fb8994fd75 (diff)
parent6ba6ca19507add38549e07058c57489a8cd98cd1 (diff)
Merge branch 'notsystemd/postmove' into notsystemd/master
# Conflicts: # src/grp-journal/systemd-journald/Makefile # src/grp-login/systemd-logind/Makefile # src/grp-machine/grp-import/systemd-export/Makefile # src/grp-machine/grp-import/systemd-import/Makefile # src/grp-machine/grp-import/systemd-pull/Makefile # src/grp-machine/systemd-machined/Makefile # src/grp-network/libnetworkd-core/Makefile # src/grp-resolve/libbasic-dns/Makefile # src/grp-resolve/systemd-resolved/Makefile # src/grp-utils/systemd-path/Makefile # src/libshared/src/Makefile # src/libsystemd-network/include/systemd-network/sd-ndisc.h # src/libsystemd/Makefile # src/libsystemd/src/test.mk # src/libudev/Makefile # src/systemd-dbus1-generator/Makefile # src/systemd-nspawn/nspawn.c Signed-off-by: Luke Shumaker <lukeshu@sbcglobal.net>
Diffstat (limited to 'src/grp-system/systemctl')
-rw-r--r--src/grp-system/systemctl/Makefile2
-rw-r--r--src/grp-system/systemctl/systemctl.c790
-rw-r--r--src/grp-system/systemctl/systemctl.xml294
3 files changed, 667 insertions, 419 deletions
diff --git a/src/grp-system/systemctl/Makefile b/src/grp-system/systemctl/Makefile
index 114e58cb27..afc8ea62cd 100644
--- a/src/grp-system/systemctl/Makefile
+++ b/src/grp-system/systemctl/Makefile
@@ -28,7 +28,7 @@ systemctl_SOURCES = \
src/systemctl/systemctl.c
systemctl_LDADD = \
- libshared.la
+ libsystemd-shared.la
files.out.all += systemctl.completion.bash
files.out.all += systemctl.completion.zsh
diff --git a/src/grp-system/systemctl/systemctl.c b/src/grp-system/systemctl/systemctl.c
index 63818d07b8..0f115db14c 100644
--- a/src/grp-system/systemctl/systemctl.c
+++ b/src/grp-system/systemctl/systemctl.c
@@ -58,6 +58,7 @@
#include "basic/process-util.h"
#include "basic/rlimit-util.h"
#include "basic/set.h"
+#include "basic/sigbus.h"
#include "basic/signal-util.h"
#include "basic/socket-util.h"
#include "basic/special.h"
@@ -86,6 +87,25 @@
#include "shared/spawn-polkit-agent.h"
#include "shared/utmp-wtmp.h"
+/* The init script exit status codes
+ 0 program is running or service is OK
+ 1 program is dead and /var/run pid file exists
+ 2 program is dead and /var/lock lock file exists
+ 3 program is not running
+ 4 program or service status is unknown
+ 5-99 reserved for future LSB use
+ 100-149 reserved for distribution use
+ 150-199 reserved for application use
+ 200-254 reserved
+*/
+enum {
+ EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0,
+ EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1,
+ EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2,
+ EXIT_PROGRAM_NOT_RUNNING = 3,
+ EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
+};
+
static char **arg_types = NULL;
static char **arg_states = NULL;
static char **arg_properties = NULL;
@@ -155,6 +175,7 @@ static bool arg_firmware_setup = false;
static bool arg_now = false;
static int daemon_reload(int argc, char *argv[], void* userdata);
+static int trivial_method(int argc, char *argv[], void *userdata);
static int halt_now(enum action a);
static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
@@ -204,6 +225,21 @@ static void release_busses(void) {
busses[w] = sd_bus_flush_close_unref(busses[w]);
}
+static int map_string_no_copy(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ char *s;
+ const char **p = userdata;
+ int r;
+
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &s);
+ if (r < 0)
+ return r;
+
+ if (!isempty(s))
+ *p = s;
+
+ return 0;
+}
+
static void ask_password_agent_open_if_enabled(void) {
/* Open the password agent as a child process if necessary */
@@ -568,7 +604,8 @@ static int get_unit_list(
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
+ if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) ||
+ sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) {
/* Fallback to legacy ListUnitsFiltered method */
fallback = true;
log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r));
@@ -714,12 +751,12 @@ static int list_units(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ pager_open(arg_no_pager, false);
+
r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (r < 0)
return r;
@@ -926,12 +963,12 @@ static int list_sockets(int argc, char *argv[], void *userdata) {
int r = 0, n;
sd_bus *bus;
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ pager_open(arg_no_pager, false);
+
n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (n < 0)
return n;
@@ -1233,12 +1270,12 @@ static int list_timers(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r = 0;
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ pager_open(arg_no_pager, false);
+
n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (n < 0)
return n;
@@ -1404,8 +1441,6 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
int r;
bool fallback = false;
- pager_open(arg_no_pager, false);
-
if (install_client_side()) {
Hashmap *h;
UnitFileList *u;
@@ -1520,6 +1555,8 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
return bus_log_parse_error(r);
}
+ pager_open(arg_no_pager, false);
+
qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
output_unit_file_list(units, c);
@@ -1768,12 +1805,12 @@ static int list_dependencies(int argc, char *argv[], void *userdata) {
} else
u = SPECIAL_DEFAULT_TARGET;
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ pager_open(arg_no_pager, false);
+
puts(u);
return list_dependencies_one(bus, u, 0, &units, 0);
@@ -1799,12 +1836,12 @@ static const struct bus_properties_map machine_info_property_map[] = {
};
static void machine_info_clear(struct machine_info *info) {
- if (info) {
- free(info->name);
- free(info->state);
- free(info->control_group);
- zero(*info);
- }
+ assert(info);
+
+ free(info->name);
+ free(info->state);
+ free(info->control_group);
+ zero(*info);
}
static void free_machines_list(struct machine_info *machine_infos, int n) {
@@ -1999,8 +2036,6 @@ static int list_machines(int argc, char *argv[], void *userdata) {
return -EPERM;
}
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
@@ -2009,6 +2044,8 @@ static int list_machines(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
+ pager_open(arg_no_pager, false);
+
qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
output_machines_list(machine_infos, r);
free_machines_list(machine_infos, r);
@@ -2212,8 +2249,6 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
int r;
bool skipped = false;
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
@@ -2254,6 +2289,8 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
+ pager_open(arg_no_pager, false);
+
output_jobs_list(jobs, c, skipped);
return 0;
}
@@ -2264,14 +2301,14 @@ static int cancel_job(int argc, char *argv[], void *userdata) {
int r = 0;
if (argc <= 1)
- return daemon_reload(argc, argv, userdata);
-
- polkit_agent_open_if_enabled();
+ return trivial_method(argc, argv, userdata);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
STRV_FOREACH(name, strv_skip(argv, 1)) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
uint32_t id;
@@ -2478,7 +2515,7 @@ static int unit_find_paths(
r = 1;
}
- if (r == 0)
+ if (r == 0 && !arg_force)
log_error("No files found for %s.", unit_name);
return r;
@@ -2674,10 +2711,9 @@ static int start_unit_one(
if (r < 0) {
const char *verb;
- if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
- /* There's always a fallback possible for
- * legacy actions. */
- return -EADDRNOTAVAIL;
+ /* There's always a fallback possible for legacy actions. */
+ if (arg_action != ACTION_SYSTEMCTL)
+ return r;
verb = method_to_verb(method);
@@ -2808,13 +2844,13 @@ static int start_unit(int argc, char *argv[], void *userdata) {
char **name;
int r = 0;
- ask_password_agent_open_if_enabled();
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ ask_password_agent_open_if_enabled();
+ polkit_agent_open_if_enabled();
+
if (arg_action == ACTION_SYSTEMCTL) {
enum action action;
@@ -2934,9 +2970,6 @@ static int logind_reboot(enum action a) {
sd_bus *bus;
int r;
- polkit_agent_open_if_enabled();
- (void) logind_set_wall_message();
-
r = acquire_bus(BUS_FULL, &bus);
if (r < 0)
return r;
@@ -2972,6 +3005,9 @@ static int logind_reboot(enum action a) {
return -EINVAL;
}
+ polkit_agent_open_if_enabled();
+ (void) logind_set_wall_message();
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
@@ -3013,6 +3049,9 @@ static int logind_check_inhibitors(enum action a) {
if (!on_tty())
return 0;
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return 0;
+
r = acquire_bus(BUS_FULL, &bus);
if (r < 0)
return r;
@@ -3233,7 +3272,7 @@ static int start_special(int argc, char *argv[], void *userdata) {
ACTION_REBOOT,
ACTION_KEXEC,
ACTION_EXIT))
- return daemon_reload(argc, argv, userdata);
+ return trivial_method(argc, argv, userdata);
/* First try logind, to allow authentication with polkit */
if (IN_SET(a,
@@ -3255,6 +3294,18 @@ static int start_special(int argc, char *argv[], void *userdata) {
return start_unit(argc, argv, userdata);
}
+static int start_system_special(int argc, char *argv[], void *userdata) {
+ /* Like start_special above, but raises an error when running in user mode */
+
+ if (arg_scope != UNIT_FILE_SYSTEM) {
+ log_error("Bad action for %s mode.",
+ arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user");
+ return -EINVAL;
+ }
+
+ return start_special(argc, argv, userdata);
+}
+
static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
_cleanup_strv_free_ char **names = NULL;
UnitActiveState active_state;
@@ -3292,12 +3343,12 @@ static int check_unit_generic(int code, const UnitActiveState good_states[], int
static int check_unit_active(int argc, char *argv[], void *userdata) {
const UnitActiveState states[] = { UNIT_ACTIVE, UNIT_RELOADING };
/* According to LSB: 3, "program is not running" */
- return check_unit_generic(3, states, ELEMENTSOF(states), strv_skip(argv, 1));
+ return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int check_unit_failed(int argc, char *argv[], void *userdata) {
const UnitActiveState states[] = { UNIT_FAILED };
- return check_unit_generic(1, states, ELEMENTSOF(states), strv_skip(argv, 1));
+ return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int kill_unit(int argc, char *argv[], void *userdata) {
@@ -3306,12 +3357,12 @@ static int kill_unit(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r, q;
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
if (!arg_kill_who)
arg_kill_who = "all";
@@ -3423,6 +3474,27 @@ static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
return 1;
}
+typedef struct UnitCondition {
+ char *name;
+ char *param;
+ bool trigger;
+ bool negate;
+ int tristate;
+
+ LIST_FIELDS(struct UnitCondition, conditions);
+} UnitCondition;
+
+static void unit_condition_free(UnitCondition *c) {
+ if (!c)
+ return;
+
+ free(c->name);
+ free(c->param);
+ free(c);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
+
typedef struct UnitStatusInfo {
const char *id;
const char *load_state;
@@ -3469,10 +3541,7 @@ typedef struct UnitStatusInfo {
usec_t condition_timestamp;
bool condition_result;
- bool failed_condition_trigger;
- bool failed_condition_negate;
- const char *failed_condition;
- const char *failed_condition_parameter;
+ LIST_HEAD(UnitCondition, conditions);
usec_t assert_timestamp;
bool assert_result;
@@ -3500,6 +3569,9 @@ typedef struct UnitStatusInfo {
/* CGroup */
uint64_t memory_current;
+ uint64_t memory_low;
+ uint64_t memory_high;
+ uint64_t memory_max;
uint64_t memory_limit;
uint64_t cpu_usage_nsec;
uint64_t tasks_current;
@@ -3508,6 +3580,25 @@ typedef struct UnitStatusInfo {
LIST_HEAD(ExecStatusInfo, exec);
} UnitStatusInfo;
+static void unit_status_info_free(UnitStatusInfo *info) {
+ ExecStatusInfo *p;
+ UnitCondition *c;
+
+ strv_free(info->documentation);
+ strv_free(info->dropin_paths);
+ strv_free(info->listen);
+
+ while ((c = info->conditions)) {
+ LIST_REMOVE(conditions, info->conditions, c);
+ unit_condition_free(c);
+ }
+
+ while ((p = info->exec)) {
+ LIST_REMOVE(exec, info->exec, p);
+ exec_status_info_free(p);
+ }
+}
+
static void print_status_info(
sd_bus *bus,
UnitStatusInfo *i,
@@ -3629,19 +3720,28 @@ static void print_status_info(
printf("\n");
if (!i->condition_result && i->condition_timestamp > 0) {
+ UnitCondition *c;
+ int n = 0;
+
s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
printf("Condition: start %scondition failed%s at %s%s%s\n",
ansi_highlight_yellow(), ansi_normal(),
s2, s1 ? "; " : "", strempty(s1));
- if (i->failed_condition_trigger)
- printf(" none of the trigger conditions were met\n");
- else if (i->failed_condition)
- printf(" %s=%s%s was not met\n",
- i->failed_condition,
- i->failed_condition_negate ? "!" : "",
- i->failed_condition_parameter);
+
+ LIST_FOREACH(conditions, c, i->conditions)
+ if (c->tristate < 0)
+ n++;
+
+ LIST_FOREACH(conditions, c, i->conditions)
+ if (c->tristate < 0)
+ printf(" %s %s=%s%s%s was not met\n",
+ --n ? special_glyph(TREE_BRANCH) : special_glyph(TREE_RIGHT),
+ c->name,
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->param);
}
if (!i->assert_result && i->assert_timestamp > 0) {
@@ -3726,7 +3826,7 @@ static void print_status_info(
if (i->running) {
_cleanup_free_ char *comm = NULL;
- get_process_comm(i->main_pid, &comm);
+ (void) get_process_comm(i->main_pid, &comm);
if (comm)
printf(" (%s)", comm);
} else if (i->exit_code > 0) {
@@ -3745,17 +3845,19 @@ static void print_status_info(
printf("signal=%s", signal_to_string(i->exit_status));
printf(")");
}
-
- if (i->control_pid > 0)
- printf(";");
}
if (i->control_pid > 0) {
_cleanup_free_ char *c = NULL;
- printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
+ if (i->main_pid > 0)
+ fputs("; Control PID: ", stdout);
+ else
+ fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
- get_process_comm(i->control_pid, &c);
+ printf(PID_FMT, i->control_pid);
+
+ (void) get_process_comm(i->control_pid, &c);
if (c)
printf(" (%s)", c);
}
@@ -3772,7 +3874,7 @@ static void print_status_info(
printf(" Tasks: %" PRIu64, i->tasks_current);
if (i->tasks_max != (uint64_t) -1)
- printf(" (limit: %" PRIi64 ")\n", i->tasks_max);
+ printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
else
printf("\n");
}
@@ -3782,10 +3884,30 @@ static void print_status_info(
printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
- if (i->memory_limit != (uint64_t) -1)
- printf(" (limit: %s)\n", format_bytes(buf, sizeof(buf), i->memory_limit));
- else
- printf("\n");
+ if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
+ i->memory_limit != CGROUP_LIMIT_MAX) {
+ const char *prefix = "";
+
+ printf(" (");
+ if (i->memory_low > 0) {
+ printf("%slow: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_low));
+ prefix = " ";
+ }
+ if (i->memory_high != CGROUP_LIMIT_MAX) {
+ printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high));
+ prefix = " ";
+ }
+ if (i->memory_max != CGROUP_LIMIT_MAX) {
+ printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
+ prefix = " ";
+ }
+ if (i->memory_limit != CGROUP_LIMIT_MAX) {
+ printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
+ prefix = " ";
+ }
+ printf(")");
+ }
+ printf("\n");
}
if (i->cpu_usage_nsec != (uint64_t) -1) {
@@ -3793,14 +3915,13 @@ static void print_status_info(
printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
}
- if (i->control_group)
- printf(" CGroup: %s\n", i->control_group);
-
- {
+ if (i->control_group) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
static const char prefix[] = " ";
unsigned c;
+ printf(" CGroup: %s\n", i->control_group);
+
c = columns();
if (c > sizeof(prefix) - 1)
c -= sizeof(prefix) - 1;
@@ -4014,6 +4135,12 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
i->assert_timestamp = (usec_t) u;
else if (streq(name, "MemoryCurrent"))
i->memory_current = u;
+ else if (streq(name, "MemoryLow"))
+ i->memory_low = u;
+ else if (streq(name, "MemoryHigh"))
+ i->memory_high = u;
+ else if (streq(name, "MemoryMax"))
+ i->memory_max = u;
else if (streq(name, "MemoryLimit"))
i->memory_limit = u;
else if (streq(name, "TasksCurrent"))
@@ -4109,13 +4236,25 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
- log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
- if (state < 0 && (!trigger || !i->failed_condition)) {
- i->failed_condition = cond;
- i->failed_condition_trigger = trigger;
- i->failed_condition_negate = negate;
- i->failed_condition_parameter = param;
- }
+ _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
+
+ log_debug("%s trigger=%d negate=%d %s →%d", cond, trigger, negate, param, state);
+
+ c = new0(UnitCondition, 1);
+ if (!c)
+ return log_oom();
+
+ c->name = strdup(cond);
+ c->param = strdup(param);
+ if (!c->name || !c->param)
+ return log_oom();
+
+ c->trigger = trigger;
+ c->negate = negate;
+ c->tristate = state;
+
+ LIST_PREPEND(conditions, i->conditions, c);
+ c = NULL;
}
if (r < 0)
return bus_log_parse_error(r);
@@ -4307,7 +4446,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
- print_prop("EnvironmentFile", "%s (ignore_errors=%s)\n", path, yes_no(ignore));
+ print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path, yes_no(ignore));
if (r < 0)
return bus_log_parse_error(r);
@@ -4499,20 +4638,29 @@ static int show_one(
const char *verb,
sd_bus *bus,
const char *path,
+ const char *unit,
bool show_properties,
bool *new_line,
bool *ellipsized) {
+ static const struct bus_properties_map property_map[] = {
+ { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state) },
+ {}
+ };
+
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- UnitStatusInfo info = {
+ _cleanup_set_free_ Set *found_properties = NULL;
+ _cleanup_(unit_status_info_free) UnitStatusInfo info = {
.memory_current = (uint64_t) -1,
+ .memory_high = CGROUP_LIMIT_MAX,
+ .memory_max = CGROUP_LIMIT_MAX,
.memory_limit = (uint64_t) -1,
.cpu_usage_nsec = (uint64_t) -1,
.tasks_current = (uint64_t) -1,
.tasks_max = (uint64_t) -1,
};
- ExecStatusInfo *p;
int r;
assert(path);
@@ -4532,6 +4680,25 @@ static int show_one(
if (r < 0)
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+ if (unit) {
+ r = bus_message_map_all_properties(reply, property_map, &info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
+
+ if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
+ log_error("Unit %s could not be found.", unit);
+
+ if (streq(verb, "status"))
+ return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+
+ return -ENOENT;
+ }
+
+ r = sd_bus_message_rewind(reply, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
+ }
+
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
return bus_log_parse_error(r);
@@ -4556,9 +4723,17 @@ static int show_one(
if (r < 0)
return bus_log_parse_error(r);
- if (show_properties)
+ if (show_properties) {
+ r = set_ensure_allocated(&found_properties, &string_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_put(found_properties, name);
+ if (r < 0 && r != EEXIST)
+ return log_oom();
+
r = print_property(name, reply, contents);
- else
+ } else
r = status_property(name, reply, &info, contents);
if (r < 0)
return r;
@@ -4579,37 +4754,24 @@ static int show_one(
return bus_log_parse_error(r);
r = 0;
+ if (show_properties) {
+ char **pp;
- if (!show_properties) {
- if (streq(verb, "help"))
- show_unit_help(&info);
- else
- print_status_info(bus, &info, ellipsized);
- }
-
- strv_free(info.documentation);
- strv_free(info.dropin_paths);
- strv_free(info.listen);
-
- if (!streq_ptr(info.active_state, "active") &&
- !streq_ptr(info.active_state, "reloading") &&
- streq(verb, "status")) {
- /* According to LSB: "program not running" */
- /* 0: program is running or service is OK
- * 1: program is dead and /run PID file exists
- * 2: program is dead and /run/lock lock file exists
- * 3: program is not running
- * 4: program or service status is unknown
- */
- if (info.pid_file && access(info.pid_file, F_OK) == 0)
- r = 1;
- else
- r = 3;
- }
+ STRV_FOREACH(pp, arg_properties)
+ if (!set_contains(found_properties, *pp)) {
+ log_warning("Property %s does not exist.", *pp);
+ r = -ENXIO;
+ }
- while ((p = info.exec)) {
- LIST_REMOVE(exec, info.exec, p);
- exec_status_info_free(p);
+ } else if (streq(verb, "help"))
+ show_unit_help(&info);
+ else if (streq(verb, "status")) {
+ print_status_info(bus, &info, ellipsized);
+
+ if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed"))
+ r = EXIT_PROGRAM_NOT_RUNNING;
+ else
+ r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
}
return r;
@@ -4679,7 +4841,7 @@ static int show_all(
if (!p)
return log_oom();
- r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
+ r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
if (r < 0)
return r;
else if (r > 0 && ret == 0)
@@ -4761,6 +4923,10 @@ static int show(int argc, char *argv[], void *userdata) {
return -EINVAL;
}
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
pager_open(arg_no_pager, false);
if (show_status)
@@ -4769,17 +4935,12 @@ static int show(int argc, char *argv[], void *userdata) {
* be split up into many files. */
setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
/* If no argument is specified inspect the manager itself */
if (show_properties && argc <= 1)
- return show_one(argv[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
+ return show_one(argv[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
if (show_status && argc <= 1) {
- pager_open(arg_no_pager, false);
show_system_status(bus);
new_line = true;
@@ -4790,7 +4951,7 @@ static int show(int argc, char *argv[], void *userdata) {
char **name;
STRV_FOREACH(name, strv_skip(argv, 1)) {
- _cleanup_free_ char *unit = NULL;
+ _cleanup_free_ char *path = NULL, *unit = NULL;
uint32_t id;
if (safe_atou32(*name, &id) < 0) {
@@ -4800,19 +4961,23 @@ static int show(int argc, char *argv[], void *userdata) {
continue;
} else if (show_properties) {
/* Interpret as job id */
- if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
+ if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
return log_oom();
} else {
/* Interpret as PID */
- r = get_unit_dbus_path_by_pid(bus, id, &unit);
+ r = get_unit_dbus_path_by_pid(bus, id, &path);
if (r < 0) {
ret = r;
continue;
}
+
+ r = unit_name_from_dbus_path(path, &unit);
+ if (r < 0)
+ return log_oom();
}
- r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized);
+ r = show_one(argv[0], bus, path, unit, show_properties, &new_line, &ellipsized);
if (r < 0)
return r;
else if (r > 0 && ret == 0)
@@ -4827,16 +4992,16 @@ static int show(int argc, char *argv[], void *userdata) {
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
- _cleanup_free_ char *unit;
+ _cleanup_free_ char *path;
- unit = unit_dbus_path_from_name(*name);
- if (!unit)
+ path = unit_dbus_path_from_name(*name);
+ if (!path)
return log_oom();
- r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized);
+ r = show_one(argv[0], bus, path, *name, show_properties, &new_line, &ellipsized);
if (r < 0)
return r;
- else if (r > 0 && ret == 0)
+ if (r > 0 && ret == 0)
ret = r;
}
}
@@ -4932,12 +5097,12 @@ static int set_property(int argc, char *argv[], void *userdata) {
char **i;
int r;
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_message_new_method_call(
bus,
&m,
@@ -4979,36 +5144,87 @@ static int set_property(int argc, char *argv[], void *userdata) {
static int daemon_reload(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
const char *method;
sd_bus *bus;
int r;
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
- if (arg_action == ACTION_RELOAD)
+ polkit_agent_open_if_enabled();
+
+ switch (arg_action) {
+
+ case ACTION_RELOAD:
method = "Reload";
- else if (arg_action == ACTION_REEXEC)
+ break;
+
+ case ACTION_REEXEC:
method = "Reexecute";
- else {
- assert(arg_action == ACTION_SYSTEMCTL);
+ break;
- method =
- streq(argv[0], "clear-jobs") ||
- streq(argv[0], "cancel") ? "ClearJobs" :
- streq(argv[0], "daemon-reexec") ? "Reexecute" :
- streq(argv[0], "reset-failed") ? "ResetFailed" :
- streq(argv[0], "halt") ? "Halt" :
- streq(argv[0], "poweroff") ? "PowerOff" :
- streq(argv[0], "reboot") ? "Reboot" :
- streq(argv[0], "kexec") ? "KExec" :
- streq(argv[0], "exit") ? "Exit" :
- /* "daemon-reload" */ "Reload";
+ case ACTION_SYSTEMCTL:
+ method = streq(argv[0], "daemon-reexec") ? "Reexecute" :
+ /* "daemon-reload" */ "Reload";
+ break;
+
+ default:
+ assert_not_reached("Unexpected action");
}
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ method);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
+ * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
+ * their timeout, and for everything else there's the same time budget in place. */
+
+ r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
+
+ /* On reexecution, we expect a disconnect, not a reply */
+ if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute"))
+ r = 0;
+
+ if (r < 0 && arg_action == ACTION_SYSTEMCTL)
+ return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
+
+ /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
+ * old ways of doing things, hence don't log any error in that case here. */
+
+ return r < 0 ? r : 0;
+}
+
+static int trivial_method(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *method;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_if_enabled();
+
+ method =
+ streq(argv[0], "clear-jobs") ||
+ streq(argv[0], "cancel") ? "ClearJobs" :
+ streq(argv[0], "reset-failed") ? "ResetFailed" :
+ streq(argv[0], "halt") ? "Halt" :
+ streq(argv[0], "reboot") ? "Reboot" :
+ streq(argv[0], "kexec") ? "KExec" :
+ streq(argv[0], "exit") ? "Exit" :
+ /* poweroff */ "PowerOff";
+
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
@@ -5018,16 +5234,11 @@ static int daemon_reload(int argc, char *argv[], void *userdata) {
&error,
NULL,
NULL);
- if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
- /* There's always a fallback possible for
- * legacy actions. */
- r = -EADDRNOTAVAIL;
- else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
- /* On reexecution, we expect a disconnect, not a
- * reply */
- r = 0;
- else if (r < 0)
- return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
+ if (r < 0 && arg_action == ACTION_SYSTEMCTL)
+ return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+
+ /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
+ * old ways of doing things, hence don't log any error in that case here. */
return r < 0 ? r : 0;
}
@@ -5039,14 +5250,14 @@ static int reset_failed(int argc, char *argv[], void *userdata) {
int r, q;
if (argc <= 1)
- return daemon_reload(argc, argv, userdata);
-
- polkit_agent_open_if_enabled();
+ return trivial_method(argc, argv, userdata);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
if (r < 0)
return log_error_errno(r, "Failed to expand names: %m");
@@ -5080,12 +5291,12 @@ static int show_environment(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
- pager_open(arg_no_pager, false);
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ pager_open(arg_no_pager, false);
+
r = sd_bus_get_property(
bus,
"org.freedesktop.systemd1",
@@ -5145,9 +5356,7 @@ static int switch_root(int argc, char *argv[], void *userdata) {
init = cmdline_init;
}
- if (isempty(init))
- init = NULL;
-
+ init = empty_to_null(init);
if (init) {
const char *root_systemd_path = NULL, *root_init_path = NULL;
@@ -5191,12 +5400,12 @@ static int set_environment(int argc, char *argv[], void *userdata) {
assert(argc > 1);
assert(argv);
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
method = streq(argv[0], "set-environment")
? "SetEnvironment"
: "UnsetEnvironment";
@@ -5228,12 +5437,12 @@ static int import_environment(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_message_new_method_call(
bus,
&m,
@@ -5391,10 +5600,8 @@ static int enable_sysv_units(const char *verb, char **args) {
}
j = wait_for_terminate(pid, &status);
- if (j < 0) {
- log_error_errno(j, "Failed to wait for child: %m");
- return j;
- }
+ if (j < 0)
+ return log_error_errno(j, "Failed to wait for child: %m");
if (status.si_code == CLD_EXITED) {
if (streq(verb, "is-enabled")) {
@@ -5464,6 +5671,46 @@ static int mangle_names(char **original_names, char ***mangled_names) {
return 0;
}
+static int unit_exists(const char *unit) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *path = NULL;
+ static const struct bus_properties_map property_map[] = {
+ { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state)},
+ {},
+ };
+ UnitStatusInfo info = {};
+ sd_bus *bus;
+ int r;
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return log_oom();
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ &error,
+ &reply,
+ "s", "");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+
+ r = bus_message_map_all_properties(reply, property_map, &info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
+
+ return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
+}
+
static int enable_unit(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **names = NULL;
const char *verb = argv[0];
@@ -5515,7 +5762,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
if (r < 0)
- return r;
+ goto finish;
r = 0;
} else {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
@@ -5525,12 +5772,20 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
const char *method;
sd_bus *bus;
- polkit_agent_open_if_enabled();
+ if (STR_IN_SET(verb, "mask", "unmask")) {
+ r = unit_exists(*names);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ log_notice("Unit %s does not exist, proceeding anyway.", *names);
+ }
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
if (streq(verb, "enable")) {
method = "EnableUnitFiles";
expect_carries_install_info = true;
@@ -5607,7 +5862,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
if (r < 0)
- return r;
+ goto finish;
/* Try to reload if enabled */
if (!arg_no_reload)
@@ -5691,12 +5946,12 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus;
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_message_new_method_call(
bus,
&m,
@@ -5753,12 +6008,12 @@ static int preset_all(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
sd_bus *bus;
- polkit_agent_open_if_enabled();
-
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
@@ -5929,7 +6184,7 @@ static int create_edit_temp_file(const char *new_path, const char *original_path
return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
} else if (r < 0)
- return log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t);
+ return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
*ret_tmp_fn = t;
t = NULL;
@@ -5952,7 +6207,7 @@ static int get_file_to_edit(
return log_oom();
if (arg_runtime) {
- run = strjoin(paths->runtime_config, name, NULL);
+ run = strjoin(paths->runtime_config, "/", name, NULL);
if (!run)
return log_oom();
}
@@ -5973,9 +6228,10 @@ static int get_file_to_edit(
return 0;
}
-static int unit_file_create_dropin(
+static int unit_file_create_new(
const LookupPaths *paths,
const char *unit_name,
+ const char *suffix,
char **ret_new_path,
char **ret_tmp_path) {
@@ -5986,7 +6242,7 @@ static int unit_file_create_dropin(
assert(ret_new_path);
assert(ret_tmp_path);
- ending = strjoina(unit_name, ".d/override.conf");
+ ending = strjoina(unit_name, suffix);
r = get_file_to_edit(paths, ending, &tmp_new_path);
if (r < 0)
return r;
@@ -6033,13 +6289,12 @@ static int unit_file_create_copy(
if (response != 'y') {
log_warning("%s ignored", unit_name);
free(tmp_new_path);
- return -1;
+ return -EKEYREJECTED;
}
}
r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
if (r < 0) {
- log_error_errno(r, "Failed to create temporary file for \"%s\": %m", tmp_new_path);
free(tmp_new_path);
return r;
}
@@ -6150,18 +6405,24 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
r = unit_find_paths(bus, *name, &lp, &path, NULL);
if (r < 0)
return r;
- else if (r == 0)
- return -ENOENT;
- else if (!path) {
- // FIXME: support units with path==NULL (no FragmentPath)
- log_error("No fragment exists for %s.", *name);
- return -ENOENT;
+ else if (!arg_force) {
+ if (r == 0) {
+ log_error("Run 'systemctl edit --force %s' to create a new unit.", *name);
+ return -ENOENT;
+ } else if (!path) {
+ // FIXME: support units with path==NULL (no FragmentPath)
+ log_error("No fragment exists for %s.", *name);
+ return -ENOENT;
+ }
}
- if (arg_full)
- r = unit_file_create_copy(&lp, *name, path, &new_path, &tmp_path);
- else
- r = unit_file_create_dropin(&lp, *name, &new_path, &tmp_path);
+ if (path) {
+ if (arg_full)
+ r = unit_file_create_copy(&lp, *name, path, &new_path, &tmp_path);
+ else
+ r = unit_file_create_new(&lp, *name, ".d/override.conf", &new_path, &tmp_path);
+ } else
+ r = unit_file_create_new(&lp, *name, NULL, &new_path, &tmp_path);
if (r < 0)
return r;
@@ -6335,7 +6596,7 @@ static void systemctl_help(void) {
" unit is required or wanted\n\n"
"Unit File Commands:\n"
" list-unit-files [PATTERN...] List installed unit files\n"
- " enable NAME... Enable one or more unit files\n"
+ " enable [NAME...|PATH...] Enable one or more unit files\n"
" disable NAME... Disable one or more unit files\n"
" reenable NAME... Reenable one or more unit files\n"
" preset NAME... Enable/disable one or more unit files\n"
@@ -7421,71 +7682,71 @@ static int systemctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units },
- { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
- { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets },
- { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers },
- { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs },
- { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines },
- { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
- { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job },
- { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
- { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */
- { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
- { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */
- { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
- { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */
- { "isolate", 2, 2, VERB_NOCHROOT, start_unit },
- { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit },
- { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
- { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
- { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed },
- { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
- { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat },
- { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
- { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
- { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
- { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
- { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment },
- { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
- { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
- { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment},
- { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_special },
- { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_special },
- { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special },
- { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed },
- { "enable", 2, VERB_ANY, 0, enable_unit },
- { "disable", 2, VERB_ANY, 0, enable_unit },
- { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
- { "reenable", 2, VERB_ANY, 0, enable_unit },
- { "preset", 2, VERB_ANY, 0, enable_unit },
- { "preset-all", VERB_ANY, 1, 0, preset_all },
- { "mask", 2, VERB_ANY, 0, enable_unit },
- { "unmask", 2, VERB_ANY, 0, enable_unit },
- { "link", 2, VERB_ANY, 0, enable_unit },
- { "revert", 2, VERB_ANY, 0, enable_unit },
- { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root },
- { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies },
- { "set-default", 2, 2, 0, set_default },
- { "get-default", VERB_ANY, 1, 0, get_default, },
- { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property },
- { "is-system-running", VERB_ANY, 1, 0, is_system_running },
- { "add-wants", 3, VERB_ANY, 0, add_dependency },
- { "add-requires", 3, VERB_ANY, 0, add_dependency },
- { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit },
+ { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
+ { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets },
+ { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers },
+ { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs },
+ { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines },
+ { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, trivial_method },
+ { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job },
+ { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
+ { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */
+ { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */
+ { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
+ { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */
+ { "isolate", 2, 2, VERB_NOCHROOT, start_unit },
+ { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit },
+ { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
+ { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
+ { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed },
+ { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
+ { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat },
+ { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
+ { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
+ { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
+ { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
+ { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment },
+ { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
+ { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
+ { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment },
+ { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_system_special },
+ { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
+ { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special },
+ { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed },
+ { "enable", 2, VERB_ANY, 0, enable_unit },
+ { "disable", 2, VERB_ANY, 0, enable_unit },
+ { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
+ { "reenable", 2, VERB_ANY, 0, enable_unit },
+ { "preset", 2, VERB_ANY, 0, enable_unit },
+ { "preset-all", VERB_ANY, 1, 0, preset_all },
+ { "mask", 2, VERB_ANY, 0, enable_unit },
+ { "unmask", 2, VERB_ANY, 0, enable_unit },
+ { "link", 2, VERB_ANY, 0, enable_unit },
+ { "revert", 2, VERB_ANY, 0, enable_unit },
+ { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root },
+ { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies },
+ { "set-default", 2, 2, 0, set_default },
+ { "get-default", VERB_ANY, 1, 0, get_default },
+ { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property },
+ { "is-system-running", VERB_ANY, 1, 0, is_system_running },
+ { "add-wants", 3, VERB_ANY, 0, add_dependency },
+ { "add-requires", 3, VERB_ANY, 0, add_dependency },
+ { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit },
{}
};
@@ -7499,7 +7760,7 @@ static int reload_with_fallback(void) {
return 0;
/* Nothing else worked, so let's try signals */
- assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
+ assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
return log_error_errno(errno, "kill() failed: %m");
@@ -7513,8 +7774,7 @@ static int start_with_fallback(void) {
if (start_unit(0, NULL, NULL) >= 0)
return 0;
- /* Nothing else worked, so let's try
- * /dev/initctl */
+ /* Nothing else worked, so let's try /dev/initctl */
if (talk_initctl() > 0)
return 0;
@@ -7580,8 +7840,6 @@ static int logind_schedule_shutdown(void) {
sd_bus *bus;
int r;
- (void) logind_set_wall_message();
-
r = acquire_bus(BUS_FULL, &bus);
if (r < 0)
return r;
@@ -7608,6 +7866,8 @@ static int logind_schedule_shutdown(void) {
if (arg_dry)
action = strjoina("dry-", action);
+ (void) logind_set_wall_message();
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
@@ -7736,6 +7996,7 @@ int main(int argc, char*argv[]) {
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
+ sigbus_install();
/* Explicitly not on_tty() to avoid setting cached value.
* This becomes relevant for piping output which might be
@@ -7797,6 +8058,8 @@ int main(int argc, char*argv[]) {
}
finish:
+ release_busses();
+
pager_close();
ask_password_agent_close();
polkit_agent_close();
@@ -7808,9 +8071,6 @@ finish:
strv_free(arg_wall);
free(arg_root);
- release_busses();
-
/* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
-
return r < 0 ? EXIT_FAILURE : r;
}
diff --git a/src/grp-system/systemctl/systemctl.xml b/src/grp-system/systemctl/systemctl.xml
index 991e9bafaf..e7880d24f7 100644
--- a/src/grp-system/systemctl/systemctl.xml
+++ b/src/grp-system/systemctl/systemctl.xml
@@ -150,11 +150,11 @@
<term><option>--all</option></term>
<listitem>
- <para>When listing units, show all loaded units, regardless
- of their state, including inactive units. When showing
- unit/job/manager properties, show all properties regardless
- whether they are set or not.</para>
- <para>To list all units installed on the system, use the
+ <para>When listing units with <command>list-units</command>, also show inactive units and
+ units which are following other units. When showing unit/job/manager properties, show all
+ properties regardless whether they are set or not.</para>
+
+ <para>To list all units installed in the file system, use the
<command>list-unit-files</command> command instead.</para>
</listitem>
</varlistentry>
@@ -481,19 +481,19 @@
<para>When used with <command>enable</command>, overwrite
any existing conflicting symlinks.</para>
- <para>When used with <command>halt</command>,
- <command>poweroff</command>, <command>reboot</command> or
- <command>kexec</command>, execute the selected operation
- without shutting down all units. However, all processes will
- be killed forcibly and all file systems are unmounted or
- remounted read-only. This is hence a drastic but relatively
- safe option to request an immediate reboot. If
- <option>--force</option> is specified twice for these
- operations, they will be executed immediately without
- terminating any processes or unmounting any file
- systems. Warning: specifying <option>--force</option> twice
- with any of these operations might result in data
- loss.</para>
+ <para>When used with <command>edit</command>, create all of the
+ specified units which do not already exist.</para>
+
+ <para>When used with <command>halt</command>, <command>poweroff</command>, <command>reboot</command> or
+ <command>kexec</command>, execute the selected operation without shutting down all units. However, all
+ processes will be killed forcibly and all file systems are unmounted or remounted read-only. This is hence a
+ drastic but relatively safe option to request an immediate reboot. If <option>--force</option> is specified
+ twice for these operations (with the exception of <command>kexec</command>), they will be executed
+ immediately, without terminating any processes or unmounting any file systems. Warning: specifying
+ <option>--force</option> twice with any of these operations might result in data loss. Note that when
+ <option>--force</option> is specified twice the selected operation is executed by
+ <command>systemctl</command> itself, and the system manager is not contacted. This means the command should
+ succeed even when the system manager hangs or crashed.</para>
</listitem>
</varlistentry>
@@ -638,10 +638,13 @@
<term><command>list-units <optional><replaceable>PATTERN</replaceable>...</optional></command></term>
<listitem>
- <para>List known units (subject to limitations specified
- with <option>-t</option>). If one or more
- <replaceable>PATTERN</replaceable>s are specified, only
- units matching one of them are shown.</para>
+ <para>List units that <command>systemd</command> has loaded. This includes units that
+ are either referenced directly or through a dependency, or units that were active in the
+ past and have failed. By default only units which are active, have pending jobs, or have
+ failed are shown; this can be changed with option <option>--all</option>. If one or more
+ <replaceable>PATTERN</replaceable>s are specified, only units matching one of them are
+ shown. The units that are shown are additionally filtered by <option>--type=</option>
+ and <option>--state=</option> if those options are specified.</para>
<para>This is the default command.</para>
</listitem>
@@ -970,71 +973,61 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>list-unit-files <optional><replaceable>PATTERN...</replaceable></optional></command></term>
<listitem>
- <para>List installed unit files and their enablement state
- (as reported by <command>is-enabled</command>). If one or
- more <replaceable>PATTERN</replaceable>s are specified,
- only units whose filename (just the last component of the
- path) matches one of them are shown.</para>
+ <para>List unit files installed on the system, in combination with their enablement state (as reported by
+ <command>is-enabled</command>). If one or more <replaceable>PATTERN</replaceable>s are specified, only unit
+ files whose name matches one of them are shown (patterns matching unit file system paths are not
+ supported).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>enable <replaceable>NAME</replaceable>...</command></term>
+ <term><command>enable <replaceable>PATH</replaceable>...</command></term>
<listitem>
- <para>Enable one or more unit files or unit file instances,
- as specified on the command line. This will create a number
- of symlinks as encoded in the <literal>[Install]</literal>
- sections of the unit files. After the symlinks have been
- created, the systemd configuration is reloaded (in a way that
- is equivalent to <command>daemon-reload</command>) to ensure
- 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, 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>.
+ <para>Enable one or more units or unit instances. This will create a set of symlinks, as encoded in the
+ <literal>[Install]</literal> sections of the indicated unit files. After the symlinks have been created,
+ the system manager configuration is reloaded (in a way equivalent to <command>daemon-reload</command>), in
+ order to ensure 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, combine this command with the <option>--now</option> switch, or invoke <command>start</command>
+ with appropriate arguments later. Note that in case of unit instance enablement (i.e. enablement of units of
+ the form <filename>foo@bar.service</filename>), symlinks named the same as instances are created in the
+ unit configuration diectory, however they point to the single template unit file they are instantiated
+ from.</para>
+
+ <para>This command expects either valid unit names (in which case various unit file directories are
+ automatically searched for unit files with appropriate names), or absolute paths to unit files (in which
+ case these files are read directly). If a specified unit file is located outside of the usual unit file
+ directories, an additional symlink is created, linking it into the unit configuration path, thus ensuring
+ it is found when requested by commands such as <command>start</command>.</para>
+
+ <para>This command will print the file system operations executed. This output may be suppressed by passing
+ <option>--quiet</option>.
</para>
- <para>Note that this operation creates only the suggested
- symlinks for the units. While this command is the
- recommended way to manipulate the unit configuration
- directory, the administrator is free to make additional
- changes manually by placing or removing symlinks in the
- directory. This is particularly useful to create
- configurations that deviate from the suggested default
- installation. In this case, the administrator must make sure
- to invoke <command>daemon-reload</command> manually as
- necessary to ensure the changes are taken into account.
+ <para>Note that this operation creates only the symlinks suggested in the <literal>[Install]</literal>
+ section of the unit files. While this command is the recommended way to manipulate the unit configuration
+ directory, the administrator is free to make additional changes manually by placing or removing symlinks
+ below this directory. This is particularly useful to create configurations that deviate from the suggested
+ default installation. In this case, the administrator must make sure to invoke
+ <command>daemon-reload</command> manually as necessary, in order to ensure the changes are taken into
+ account.
</para>
- <para>Enabling units should not be confused with starting
- (activating) units, as done by the <command>start</command>
- command. Enabling and starting units is orthogonal: units
- may be enabled without being started and started without
- being enabled. Enabling simply hooks the unit into various
- suggested places (for example, so that the unit is
- automatically started on boot or when a particular kind of
- hardware is plugged in). Starting actually spawns the daemon
- process (in case of service units), or binds the socket (in
- case of socket units), and so on.</para>
-
- <para>Depending on whether <option>--system</option>,
- <option>--user</option>, <option>--runtime</option>,
- or <option>--global</option> is specified, this enables the unit
- for the system, for the calling user only, for only this boot of
- the system, or for all future logins of all users, or only this
- boot. Note that in the last case, no systemd daemon
- configuration is reloaded.</para>
-
- <para>Using <command>enable</command> on masked units
- results in an error.</para>
+ <para>Enabling units should not be confused with starting (activating) units, as done by the
+ <command>start</command> command. Enabling and starting units is orthogonal: units may be enabled without
+ being started and started without being enabled. Enabling simply hooks the unit into various suggested
+ places (for example, so that the unit is automatically started on boot or when a particular kind of
+ hardware is plugged in). Starting actually spawns the daemon process (in case of service units), or binds
+ the socket (in case of socket units), and so on.</para>
+
+ <para>Depending on whether <option>--system</option>, <option>--user</option>, <option>--runtime</option>,
+ or <option>--global</option> is specified, this enables the unit for the system, for the calling user only,
+ for only this boot of the system, or for all future logins of all users, or only this boot. Note that in
+ the last case, no systemd daemon configuration is reloaded.</para>
+
+ <para>Using <command>enable</command> on masked units is not supported and results in an error.</para>
</listitem>
</varlistentry>
@@ -1042,28 +1035,31 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>disable <replaceable>NAME</replaceable>...</command></term>
<listitem>
- <para>Disables one or more units. This removes all symlinks
- to the specified unit files from the unit configuration
- directory, and hence undoes the changes made by
- <command>enable</command>. Note however that this removes
- all symlinks to the unit files (i.e. including manual
- additions), not just those actually created by
- <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, 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>.
+ <para>Disables one or more units. This removes all symlinks to the unit files backing the specified units
+ from the unit configuration directory, and hence undoes any changes made by <command>enable</command> or
+ <command>link</command>. Note that this removes <emphasis>all</emphasis> symlinks to matching unit files,
+ including manually created symlinks, and not just those actually created by <command>enable</command> or
+ <command>link</command>. Note that while <command>disable</command> undoes the effect of
+ <command>enable</command>, the two commands are otherwise not symmetric, as <command>disable</command> may
+ remove more symlinks than a prior <command>enable</command> invocation of the same unit created.</para>
+
+ <para>This command expects valid unit names only, it does not accept paths to unit files.</para>
+
+ <para>In addition to the units specified as arguments, all units are disabled that are listed in the
+ <varname>Also=</varname> setting contained in the <literal>[Install]</literal> section of any of the unit
+ files being operated on.</para>
+
+ <para>This command implicitly reloads the system manager configuration after completing the operation. Note
+ that this command does not implicitly stop the units that are being disabled. If this is desired, either
+ combine this command with the <option>--now</option> switch, or invoke the <command>stop</command> command
+ with appropriate arguments later.</para>
+
+ <para>This command will print information about the file system operations (symlink removals)
+ executed. This output may be suppressed by passing <option>--quiet</option>.
</para>
- <para>This command honors <option>--system</option>,
- <option>--user</option>, <option>--runtime</option> and
- <option>--global</option> in a similar way as
- <command>enable</command>.</para>
+ <para>This command honors <option>--system</option>, <option>--user</option>, <option>--runtime</option>
+ and <option>--global</option> in a similar way as <command>enable</command>.</para>
</listitem>
</varlistentry>
@@ -1071,12 +1067,10 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>reenable <replaceable>NAME</replaceable>...</command></term>
<listitem>
- <para>Reenable one or more unit files, as specified on the
- command line. This is a combination of
- <command>disable</command> and <command>enable</command> and
- is useful to reset the symlinks a unit is enabled with to
- the defaults configured in the <literal>[Install]</literal>
- section of the unit file.</para>
+ <para>Reenable one or more units, as specified on the command line. This is a combination of
+ <command>disable</command> and <command>enable</command> and is useful to reset the symlinks a unit file is
+ enabled with to the defaults configured in its <literal>[Install]</literal> section. This commands expects
+ a unit uname only, it does not accept paths to unit files.</para>
</listitem>
</varlistentry>
@@ -1207,16 +1201,13 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>mask <replaceable>NAME</replaceable>...</command></term>
<listitem>
- <para>Mask one or more unit files, as specified on the
- command line. This will link these units to
- <filename>/dev/null</filename>, making it impossible to
- start them. This is a stronger version of
- <command>disable</command>, since it prohibits all kinds of
- 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. The <option>--now</option>
- option can be used to ensure that the units are also stopped.</para>
+ <para>Mask one or more units, as specified on the command line. This will link these unit files to
+ <filename>/dev/null</filename>, making it impossible to start them. This is a stronger version of
+ <command>disable</command>, since it prohibits all kinds of 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. The <option>--now</option> option may be used to
+ ensure that the units are also stopped. This command expects valid unit names only, it does not accept unit
+ file paths.</para>
</listitem>
</varlistentry>
@@ -1224,23 +1215,20 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>unmask <replaceable>NAME</replaceable>...</command></term>
<listitem>
- <para>Unmask one or more unit files, as specified on the
- command line. This will undo the effect of
- <command>mask</command>.</para>
+ <para>Unmask one or more unit files, as specified on the command line. This will undo the effect of
+ <command>mask</command>. This command expects valid unit names only, it does not accept unit file
+ paths.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><command>link <replaceable>FILENAME</replaceable>...</command></term>
+ <term><command>link <replaceable>PATH</replaceable>...</command></term>
<listitem>
- <para>Link a unit file that is not in the unit file search
- paths into the unit file search path. This requires an
- absolute path to a unit file. The effect of this can be
- undone with <command>disable</command>. The effect of this
- command is that a unit file is available for
- <command>start</command> and other commands although it
- is not installed directly in the unit search path.</para>
+ <para>Link a unit file that is not in the unit file search paths into the unit file search path. This
+ command expects an absolute path to a unit file. The effect of this may be undone with
+ <command>disable</command>. The effect of this command is that a unit file is made available for commands
+ such as <command>start</command>, even though it is not installed directly in the unit search path.</para>
</listitem>
</varlistentry>
@@ -1304,6 +1292,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<para>If <option>--full</option> is specified, this will copy the
original units instead of creating drop-in files.</para>
+ <para>If <option>--force</option> is specified and any units do
+ not already exist, new unit files will be opened for editing.</para>
+
<para>If <option>--runtime</option> is specified, the changes will
be made temporarily in <filename>/run</filename> and they will be
lost on the next reboot.</para>
@@ -1600,48 +1591,45 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>halt</command></term>
<listitem>
- <para>Shut down and halt the system. This is mostly equivalent to
- <command>start halt.target --job-mode=replace-irreversibly</command>, but also
- prints a wall message to all users. If combined with
- <option>--force</option>, shutdown of all running services is
- skipped, however all processes are killed and all file
- systems are unmounted or mounted read-only, immediately
- followed by the system halt. If <option>--force</option> is
- specified twice, the operation is immediately executed
- without terminating any processes or unmounting any file
- systems. This may result in data loss.</para>
+ <para>Shut down and halt the system. This is mostly equivalent to <command>start halt.target
+ --job-mode=replace-irreversibly</command>, but also prints a wall message to all users. If combined with
+ <option>--force</option>, shutdown of all running services is skipped, however all processes are killed and
+ all file systems are unmounted or mounted read-only, immediately followed by the system halt. If
+ <option>--force</option> is specified twice, the operation is immediately executed without terminating any
+ processes or unmounting any file systems. This may result in data loss. Note that when
+ <option>--force</option> is specified twice the halt operation is executed by
+ <command>systemctl</command> itself, and the system manager is not contacted. This means the command should
+ succeed even when the system manager hangs or crashed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>poweroff</command></term>
<listitem>
- <para>Shut down and power-off the system. This is mostly
- equivalent to <command>start poweroff.target --job-mode=replace-irreversibly</command>,
- but also prints a wall message to all users. If combined with
- <option>--force</option>, shutdown of all running services is
- skipped, however all processes are killed and all file
- systems are unmounted or mounted read-only, immediately
- followed by the powering off. If <option>--force</option> is
- specified twice, the operation is immediately executed
- without terminating any processes or unmounting any file
- systems. This may result in data loss.</para>
+ <para>Shut down and power-off the system. This is mostly equivalent to <command>start poweroff.target
+ --job-mode=replace-irreversibly</command>, but also prints a wall message to all users. If combined with
+ <option>--force</option>, shutdown of all running services is skipped, however all processes are killed and
+ all file systems are unmounted or mounted read-only, immediately followed by the powering off. If
+ <option>--force</option> is specified twice, the operation is immediately executed without terminating any
+ processes or unmounting any file systems. This may result in data loss. Note that when
+ <option>--force</option> is specified twice the power-off operation is executed by
+ <command>systemctl</command> itself, and the system manager is not contacted. This means the command should
+ succeed even when the system manager hangs or crashed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>reboot <optional><replaceable>arg</replaceable></optional></command></term>
<listitem>
- <para>Shut down and reboot the system. This is mostly
- equivalent to <command>start reboot.target --job-mode=replace-irreversibly</command>,
- but also prints a wall message to all users. If combined with
- <option>--force</option>, shutdown of all running services is
- skipped, however all processes are killed and all file
- systems are unmounted or mounted read-only, immediately
- followed by the reboot. If <option>--force</option> is
- specified twice, the operation is immediately executed
- without terminating any processes or unmounting any file
- systems. This may result in data loss.</para>
+ <para>Shut down and reboot the system. This is mostly equivalent to <command>start reboot.target
+ --job-mode=replace-irreversibly</command>, but also prints a wall message to all users. If combined with
+ <option>--force</option>, shutdown of all running services is skipped, however all processes are killed and
+ all file systems are unmounted or mounted read-only, immediately followed by the reboot. If
+ <option>--force</option> is specified twice, the operation is immediately executed without terminating any
+ processes or unmounting any file systems. This may result in data loss. Note that when
+ <option>--force</option> is specified twice the reboot operation is executed by
+ <command>systemctl</command> itself, and the system manager is not contacted. This means the command should
+ succeed even when the system manager hangs or crashed.</para>
<para>If the optional argument
<replaceable>arg</replaceable> is given, it will be passed