summaryrefslogtreecommitdiff
path: root/src/grp-system/systemctl
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-12-17 03:11:52 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-12-17 03:11:52 -0500
commitb849891b5dde5ee14ab8b7b7db74e65a4a38d993 (patch)
tree29bb0e6fda9b4b170041913de495da057bbe3621 /src/grp-system/systemctl
parent004efebf9cc559ea131bb9460ee0ee198e2d5da7 (diff)
parent881228ff72434a0e3401a16bd87f179ef0ab1619 (diff)
Merge branch 'notsystemd/postmove' into notsystemd/master
# Conflicts: # src/grp-journal/libjournal-core/.gitignore # src/grp-system/libcore/include/core/mount.h
Diffstat (limited to 'src/grp-system/systemctl')
-rw-r--r--src/grp-system/systemctl/systemctl.c527
-rw-r--r--src/grp-system/systemctl/systemctl.completion.bash.in43
-rw-r--r--src/grp-system/systemctl/systemctl.completion.zsh.in18
-rw-r--r--src/grp-system/systemctl/systemctl.xml117
-rw-r--r--src/grp-system/systemctl/systemd.preset.xml4
5 files changed, 543 insertions, 166 deletions
diff --git a/src/grp-system/systemctl/systemctl.c b/src/grp-system/systemctl/systemctl.c
index ab9fc4a427..086c9b494b 100644
--- a/src/grp-system/systemctl/systemctl.c
+++ b/src/grp-system/systemctl/systemctl.c
@@ -119,6 +119,7 @@ static enum dependency {
} arg_dependency = DEPENDENCY_FORWARD;
static const char *arg_job_mode = "replace";
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
+static bool arg_wait = false;
static bool arg_no_block = false;
static bool arg_no_legend = false;
static bool arg_no_pager = false;
@@ -189,6 +190,11 @@ typedef enum BusFocus {
static sd_bus *busses[_BUS_FOCUS_MAX] = {};
+static UnitFileFlags args_to_flags(void) {
+ return (arg_runtime ? UNIT_FILE_RUNTIME : 0) |
+ (arg_force ? UNIT_FILE_FORCE : 0);
+}
+
static int acquire_bus(BusFocus focus, sd_bus **ret) {
int r;
@@ -362,22 +368,24 @@ static int compare_unit_info(const void *a, const void *b) {
return strcasecmp(u->id, v->id);
}
+static const char* unit_type_suffix(const char *name) {
+ const char *dot;
+
+ dot = strrchr(name, '.');
+ if (!dot)
+ return "";
+
+ return dot + 1;
+}
+
static bool output_show_unit(const UnitInfo *u, char **patterns) {
assert(u);
if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
return false;
- if (arg_types) {
- const char *dot;
-
- dot = strrchr(u->id, '.');
- if (!dot)
- return false;
-
- if (!strv_find(arg_types, dot+1))
- return false;
- }
+ if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
+ return false;
if (arg_all)
return true;
@@ -403,7 +411,7 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) {
}
static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
- unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
+ unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len, max_desc_len;
const UnitInfo *u;
unsigned n_shown = 0;
int job_count = 0;
@@ -413,13 +421,14 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
active_len = strlen("ACTIVE");
sub_len = strlen("SUB");
job_len = strlen("JOB");
- desc_len = 0;
+ max_desc_len = strlen("DESCRIPTION");
for (u = unit_infos; u < unit_infos + c; u++) {
max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
load_len = MAX(load_len, strlen(u->load_state));
active_len = MAX(active_len, strlen(u->active_state));
sub_len = MAX(sub_len, strlen(u->sub_state));
+ max_desc_len = MAX(max_desc_len, strlen(u->description));
if (u->job_id != 0) {
job_len = MAX(job_len, strlen(u->job_type));
@@ -435,7 +444,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
if (!arg_full && original_stdout_is_tty) {
unsigned basic_len;
- id_len = MIN(max_id_len, 25u);
+ id_len = MIN(max_id_len, 25u); /* as much as it needs, but at most 25 for now */
basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
if (job_count)
@@ -448,34 +457,38 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
/* Either UNIT already got 25, or is fully satisfied.
* Grant up to 25 to DESC now. */
incr = MIN(extra_len, 25u);
- desc_len += incr;
+ desc_len = incr;
extra_len -= incr;
- /* split the remaining space between UNIT and DESC,
- * but do not give UNIT more than it needs. */
+ /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
+ * description but not more than it needs. */
if (extra_len > 0) {
- incr = MIN(extra_len / 2, max_id_len - id_len);
+ incr = MIN(max_id_len - id_len, extra_len);
id_len += incr;
- desc_len += extra_len - incr;
+ desc_len += MIN(extra_len - incr, max_desc_len - desc_len);
}
}
- } else
+ } else {
id_len = max_id_len;
+ desc_len = max_desc_len;
+ }
for (u = unit_infos; u < unit_infos + c; u++) {
_cleanup_free_ char *e = NULL, *j = NULL;
+ const char *on_underline = "", *off_underline = "";
const char *on_loaded = "", *off_loaded = "";
const char *on_active = "", *off_active = "";
const char *on_circle = "", *off_circle = "";
const char *id;
- bool circle = false;
+ bool circle = false, underline = false;
if (!n_shown && !arg_no_legend) {
if (circle_len > 0)
fputs(" ", stdout);
- printf("%-*s %-*s %-*s %-*s ",
+ printf("%s%-*s %-*s %-*s %-*s ",
+ ansi_underline(),
id_len, "UNIT",
load_len, "LOAD",
active_len, "ACTIVE",
@@ -484,23 +497,34 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
if (job_count)
printf("%-*s ", job_len, "JOB");
- if (!arg_full && arg_no_pager)
- printf("%.*s\n", desc_len, "DESCRIPTION");
- else
- printf("%s\n", "DESCRIPTION");
+ printf("%-*.*s%s\n",
+ desc_len,
+ !arg_full && arg_no_pager ? (int) desc_len : -1,
+ "DESCRIPTION",
+ ansi_normal());
}
n_shown++;
+ if (u + 1 < unit_infos + c &&
+ !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
+ on_underline = ansi_underline();
+ off_underline = ansi_normal();
+ underline = true;
+ }
+
if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
- on_loaded = ansi_highlight_red();
on_circle = ansi_highlight_yellow();
- off_loaded = off_circle = ansi_normal();
+ off_circle = ansi_normal();
circle = true;
+ on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ off_loaded = underline ? on_underline : ansi_normal();
} else if (streq(u->active_state, "failed") && !arg_plain) {
- on_circle = on_active = ansi_highlight_red();
- off_circle = off_active = ansi_normal();
+ on_circle = ansi_highlight_red();
+ off_circle = ansi_normal();
circle = true;
+ on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ off_active = underline ? on_underline : ansi_normal();
}
if (u->machine) {
@@ -523,17 +547,19 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
if (circle_len > 0)
printf("%s%s%s ", on_circle, circle ? special_glyph(BLACK_CIRCLE) : " ", off_circle);
- printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
+ printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
+ on_underline,
on_active, id_len, id, off_active,
on_loaded, load_len, u->load_state, off_loaded,
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
- if (desc_len > 0)
- printf("%.*s\n", desc_len, u->description);
- else
- printf("%s\n", u->description);
+ printf("%-*.*s%s\n",
+ desc_len,
+ !arg_full && arg_no_pager ? (int) desc_len : -1,
+ u->description,
+ off_underline);
}
if (!arg_no_legend) {
@@ -1395,35 +1421,46 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
id_cols = max_id_len;
if (!arg_no_legend && c > 0)
- printf("%-*s %-*s\n",
+ printf("%s%-*s %-*s%s\n",
+ ansi_underline(),
id_cols, "UNIT FILE",
- state_cols, "STATE");
+ state_cols, "STATE",
+ ansi_normal());
for (u = units; u < units + c; u++) {
_cleanup_free_ char *e = NULL;
- const char *on, *off;
+ const char *on, *off, *on_underline = "", *off_underline = "";
const char *id;
+ bool underline = false;
+
+ if (u + 1 < units + c &&
+ !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) {
+ on_underline = ansi_underline();
+ off_underline = ansi_normal();
+ underline = true;
+ }
if (IN_SET(u->state,
UNIT_FILE_MASKED,
UNIT_FILE_MASKED_RUNTIME,
UNIT_FILE_DISABLED,
- UNIT_FILE_BAD)) {
- on = ansi_highlight_red();
- off = ansi_normal();
- } else if (u->state == UNIT_FILE_ENABLED) {
- on = ansi_highlight_green();
- off = ansi_normal();
- } else
- on = off = "";
+ UNIT_FILE_BAD))
+ on = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ else if (u->state == UNIT_FILE_ENABLED)
+ on = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
+ else
+ on = on_underline;
+ off = off_underline;
id = basename(u->path);
e = arg_full ? NULL : ellipsize(id, id_cols, 33);
- printf("%-*s %s%-*s%s\n",
+ printf("%s%-*s %s%-*s%s%s\n",
+ on_underline,
id_cols, e ? e : id,
- on, state_cols, unit_file_state_to_string(u->state), off);
+ on, state_cols, unit_file_state_to_string(u->state), off,
+ off_underline);
}
if (!arg_no_legend)
@@ -2111,7 +2148,7 @@ static int set_default(int argc, char *argv[], void *userdata) {
return log_error_errno(r, "Failed to mangle unit name: %m");
if (install_client_side()) {
- r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
+ r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
if (r > 0)
@@ -2680,13 +2717,92 @@ static const char *method_to_verb(const char *method) {
return "n/a";
}
+typedef struct {
+ sd_bus_slot *match;
+ sd_event *event;
+ Set *unit_paths;
+ bool any_failed;
+} WaitContext;
+
+static void wait_context_free(WaitContext *c) {
+ c->match = sd_bus_slot_unref(c->match);
+ c->event = sd_event_unref(c->event);
+ c->unit_paths = set_free_free(c->unit_paths);
+}
+
+static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ WaitContext *c = userdata;
+ const char *path;
+ int r;
+
+ path = sd_bus_message_get_path(m);
+ if (!set_contains(c->unit_paths, path))
+ return 0;
+
+ /* Check if ActiveState changed to inactive/failed */
+ /* (s interface, a{sv} changed_properties, as invalidated_properties) */
+ r = sd_bus_message_skip(m, "s");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ const char *s;
+
+ r = sd_bus_message_read(m, "s", &s);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (streq(s, "ActiveState")) {
+ bool is_failed;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read(m, "s", &s);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ is_failed = streq(s, "failed");
+ if (streq(s, "inactive") || is_failed) {
+ log_debug("%s became %s, dropping from --wait tracking", path, s);
+ free(set_remove(c->unit_paths, path));
+ c->any_failed = c->any_failed || is_failed;
+ } else
+ log_debug("ActiveState on %s changed to %s", path, s);
+
+ break; /* no need to dissect the rest of the message */
+ } else {
+ /* other property */
+ r = sd_bus_message_skip(m, "v");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (set_isempty(c->unit_paths))
+ sd_event_exit(c->event, EXIT_SUCCESS);
+
+ return 0;
+}
+
static int start_unit_one(
sd_bus *bus,
const char *method,
const char *name,
const char *mode,
sd_bus_error *error,
- BusWaitForJobs *w) {
+ BusWaitForJobs *w,
+ WaitContext *wait_context) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *path;
@@ -2697,6 +2813,40 @@ static int start_unit_one(
assert(mode);
assert(error);
+ if (wait_context) {
+ _cleanup_free_ char *unit_path = NULL;
+ const char* mt;
+
+ log_debug("Watching for property changes of %s", name);
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "RefUnit",
+ error,
+ NULL,
+ "s", name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to RefUnit %s: %s", name, bus_error_message(error, r));
+
+ unit_path = unit_dbus_path_from_name(name);
+ if (!unit_path)
+ return log_oom();
+
+ r = set_put_strdup(wait_context->unit_paths, unit_path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add unit path %s to set: %m", unit_path);
+
+ mt = strjoina("type='signal',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "path='", unit_path, "',"
+ "member='PropertiesChanged'");
+ r = sd_bus_add_match(bus, &wait_context->match, mt, on_properties_changed, wait_context);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add match for PropertiesChanged signal: %m");
+ }
+
log_debug("Calling manager for %s on %s, %s", method, name, mode);
r = sd_bus_call_method(
@@ -2721,9 +2871,10 @@ static int start_unit_one(
if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
!sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
- log_error("See %s logs and 'systemctl%s status %s' for details.",
+ log_error("See %s logs and 'systemctl%s status%s %s' for details.",
arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ name[0] == '-' ? " --" : "",
name);
return r;
@@ -2841,10 +2992,18 @@ static int start_unit(int argc, char *argv[], void *userdata) {
const char *method, *mode, *one_name, *suffix = NULL;
_cleanup_strv_free_ char **names = NULL;
sd_bus *bus;
+ _cleanup_(wait_context_free) WaitContext wait_context = {};
char **name;
int r = 0;
- r = acquire_bus(BUS_MANAGER, &bus);
+ if (arg_wait && !strstr(argv[0], "start")) {
+ log_error("--wait may only be used with a command that starts units.");
+ return -EINVAL;
+ }
+
+ /* we cannot do sender tracking on the private bus, so we need the full
+ * one for RefUnit to implement --wait */
+ r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus);
if (r < 0)
return r;
@@ -2888,11 +3047,36 @@ static int start_unit(int argc, char *argv[], void *userdata) {
return log_error_errno(r, "Could not watch jobs: %m");
}
+ if (arg_wait) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+ wait_context.unit_paths = set_new(&string_hash_ops);
+ if (!wait_context.unit_paths)
+ return log_oom();
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Subscribe",
+ &error,
+ NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable subscription: %s", bus_error_message(&error, r));
+ r = sd_event_default(&wait_context.event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate event loop: %m");
+ r = sd_bus_attach_event(bus, wait_context.event, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach bus to event loop: %m");
+ }
+
STRV_FOREACH(name, names) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int q;
- q = start_unit_one(bus, method, *name, mode, &error, w);
+ q = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
if (r >= 0 && q < 0)
r = translate_bus_error_to_exit_status(q, &error);
}
@@ -2924,6 +3108,15 @@ static int start_unit(int argc, char *argv[], void *userdata) {
check_triggering_units(bus, *name);
}
+ if (r >= 0 && arg_wait) {
+ int q;
+ q = sd_event_loop(wait_context.event);
+ if (q < 0)
+ return log_error_errno(q, "Failed to run event loop: %m");
+ if (wait_context.any_failed)
+ r = EXIT_FAILURE;
+ }
+
return r;
}
@@ -3121,7 +3314,7 @@ static int logind_check_inhibitors(enum action a) {
if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
continue;
- if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
+ if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty"))
continue;
sd_session_get_tty(*s, &tty);
@@ -3385,9 +3578,9 @@ static int kill_unit(int argc, char *argv[], void *userdata) {
"KillUnit",
&error,
NULL,
- "ssi", *names, kill_who ? kill_who : arg_kill_who, arg_signal);
+ "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal);
if (q < 0) {
- log_error_errno(q, "Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
+ log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q));
if (r == 0)
r = q;
}
@@ -3572,6 +3765,7 @@ typedef struct UnitStatusInfo {
uint64_t memory_low;
uint64_t memory_high;
uint64_t memory_max;
+ uint64_t memory_swap_max;
uint64_t memory_limit;
uint64_t cpu_usage_nsec;
uint64_t tasks_current;
@@ -3621,7 +3815,7 @@ static void print_status_info(
if (streq_ptr(i->active_state, "failed")) {
active_on = ansi_highlight_red();
active_off = ansi_normal();
- } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
+ } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) {
active_on = ansi_highlight_green();
active_off = ansi_normal();
} else
@@ -3702,12 +3896,10 @@ static void print_status_info(
if (!isempty(i->result) && !streq(i->result, "success"))
printf(" (Result: %s)", i->result);
- timestamp = (streq_ptr(i->active_state, "active") ||
- streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
- (streq_ptr(i->active_state, "inactive") ||
- streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
- streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
- i->active_exit_timestamp;
+ timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
+ STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp :
+ STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp :
+ i->active_exit_timestamp;
s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
s2 = format_timestamp(since2, sizeof(since2), timestamp);
@@ -3787,7 +3979,7 @@ static void print_status_info(
argv = strv_join(p->argv, " ");
printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
- good = is_clean_exit_lsb(p->code, p->status, NULL);
+ good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
if (!good) {
on = ansi_highlight_red();
off = ansi_normal();
@@ -3884,7 +4076,8 @@ static void print_status_info(
printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
- if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
+ if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX ||
+ i->memory_max != CGROUP_LIMIT_MAX || i->memory_swap_max != CGROUP_LIMIT_MAX ||
i->memory_limit != CGROUP_LIMIT_MAX) {
const char *prefix = "";
@@ -3901,6 +4094,10 @@ static void print_status_info(
printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
prefix = " ";
}
+ if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
+ printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
+ prefix = " ";
+ }
if (i->memory_limit != CGROUP_LIMIT_MAX) {
printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
prefix = " ";
@@ -4141,6 +4338,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
i->memory_high = u;
else if (streq(name, "MemoryMax"))
i->memory_max = u;
+ else if (streq(name, "MemorySwapMax"))
+ i->memory_swap_max = u;
else if (streq(name, "MemoryLimit"))
i->memory_limit = u;
else if (streq(name, "TasksCurrent"))
@@ -4575,7 +4774,8 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return 0;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "IODeviceWeight") || streq(name, "BlockIODeviceWeight"))) {
+ } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
const char *path;
uint64_t weight;
@@ -4594,8 +4794,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return 0;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (cgroup_io_limit_type_from_string(name) >= 0 ||
- streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
+ } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ (cgroup_io_limit_type_from_string(name) >= 0 ||
+ STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
const char *path;
uint64_t bandwidth;
@@ -4656,6 +4857,7 @@ static int show_one(
.memory_current = (uint64_t) -1,
.memory_high = CGROUP_LIMIT_MAX,
.memory_max = CGROUP_LIMIT_MAX,
+ .memory_swap_max = CGROUP_LIMIT_MAX,
.memory_limit = (uint64_t) -1,
.cpu_usage_nsec = (uint64_t) -1,
.tasks_current = (uint64_t) -1,
@@ -4771,7 +4973,7 @@ static int show_one(
else if (streq(verb, "status")) {
print_status_info(bus, &info, ellipsized);
- if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed"))
+ if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
r = EXIT_PROGRAM_NOT_RUNNING;
else
r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
@@ -5076,6 +5278,20 @@ static int cat(int argc, char *argv[], void *userdata) {
else
puts("");
+ if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */
+ fprintf(stderr,
+ "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
+ "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
+ "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
+ "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
+ ansi_highlight_red(),
+ *name,
+ ansi_highlight_red(),
+ ansi_highlight_red(),
+ ansi_highlight_red(),
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ ansi_normal());
+
if (fragment_path) {
r = cat_file(fragment_path, false);
if (r < 0)
@@ -5097,7 +5313,6 @@ static int set_property(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *n = NULL;
sd_bus *bus;
- char **i;
int r;
r = acquire_bus(BUS_MANAGER, &bus);
@@ -5128,11 +5343,9 @@ static int set_property(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- STRV_FOREACH(i, strv_skip(argv, 2)) {
- r = bus_append_unit_property_assignment(m, *i);
- if (r < 0)
- return r;
- }
+ r = bus_append_unit_property_assignment_many(m, strv_skip(argv, 2));
+ if (r < 0)
+ return r;
r = sd_bus_message_close_container(m);
if (r < 0)
@@ -5570,10 +5783,12 @@ static int enable_sysv_units(const char *verb, char **args) {
if (!found_sysv)
continue;
- if (found_native)
- log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
- else
- log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
+ if (!arg_quiet) {
+ if (found_native)
+ log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
+ else
+ log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
+ }
if (!isempty(arg_root))
argv[c++] = q = strappend("--root=", arg_root);
@@ -5674,6 +5889,29 @@ static int mangle_names(char **original_names, char ***mangled_names) {
return 0;
}
+static int normalize_names(char **names, bool warn_if_path) {
+ char **u;
+ bool was_path = false;
+
+ STRV_FOREACH(u, names) {
+ int r;
+
+ if (!is_path(*u))
+ continue;
+
+ r = free_and_strdup(u, basename(*u));
+ if (r < 0)
+ return log_error_errno(r, "Failed to normalize unit file path: %m");
+
+ was_path = true;
+ }
+
+ if (warn_if_path && was_path)
+ log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
+
+ 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;
@@ -5741,23 +5979,32 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
return daemon_reload(argc, argv, userdata);
}
+ if (streq(verb, "disable")) {
+ r = normalize_names(names, true);
+ if (r < 0)
+ return r;
+ }
+
if (install_client_side()) {
+ UnitFileFlags flags;
+
+ flags = args_to_flags();
if (streq(verb, "enable")) {
- r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
+ r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "disable"))
- r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
+ r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "reenable")) {
- r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
+ r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "link"))
- r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
+ r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "preset")) {
- r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
+ r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
} else if (streq(verb, "mask"))
- r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
+ r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "unmask"))
- r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
+ r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "revert"))
r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes);
else
@@ -5939,7 +6186,7 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
assert_not_reached("Unknown verb");
if (install_client_side()) {
- r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
+ r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes);
unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
if (r > 0)
@@ -6001,7 +6248,7 @@ static int preset_all(int argc, char *argv[], void *userdata) {
int r;
if (install_client_side()) {
- r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
+ r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes);
unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
if (r > 0)
@@ -6050,6 +6297,63 @@ finish:
return r;
}
+static int show_installation_targets_client_side(const char *name) {
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0, i;
+ UnitFileFlags flags;
+ char **p;
+ int r;
+
+ p = STRV_MAKE(name);
+ flags = UNIT_FILE_DRY_RUN |
+ (arg_runtime ? UNIT_FILE_RUNTIME : 0);
+
+ r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get file links for %s: %m", name);
+
+ for (i = 0; i < n_changes; i++)
+ if (changes[i].type == UNIT_FILE_UNLINK)
+ printf(" %s\n", changes[i].path);
+
+ return 0;
+}
+
+static int show_installation_targets(sd_bus *bus, const char *name) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *link;
+ int r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnitFileLinks",
+ &error,
+ &reply,
+ "sb", name, arg_runtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "s", &link)) > 0)
+ printf(" %s\n", link);
+
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
static int unit_is_enabled(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **names = NULL;
@@ -6068,7 +6372,6 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
enabled = r > 0;
if (install_client_side()) {
-
STRV_FOREACH(name, names) {
UnitFileState state;
@@ -6084,8 +6387,14 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
UNIT_FILE_GENERATED))
enabled = true;
- if (!arg_quiet)
+ if (!arg_quiet) {
puts(unit_file_state_to_string(state));
+ if (arg_full) {
+ r = show_installation_targets_client_side(*name);
+ if (r < 0)
+ return r;
+ }
+ }
}
r = 0;
@@ -6120,8 +6429,14 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
enabled = true;
- if (!arg_quiet)
+ if (!arg_quiet) {
puts(s);
+ if (arg_full) {
+ r = show_installation_targets(bus, *name);
+ if (r < 0)
+ return r;
+ }
+ }
}
}
@@ -6534,9 +6849,9 @@ static void systemctl_help(void) {
" -t --type=TYPE List units of a particular type\n"
" --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
" -p --property=NAME Show only properties by this name\n"
- " -a --all Show all loaded units/properties, including dead/empty\n"
- " ones. To list all units installed on the system, use\n"
- " the 'list-unit-files' command instead.\n"
+ " -a --all Show all properties/all units currently in memory,\n"
+ " including dead/empty ones. To list all units installed on\n"
+ " the system, use the 'list-unit-files' command instead.\n"
" -l --full Don't ellipsize unit names on output\n"
" -r --recursive Show unit list of host and local containers\n"
" --reverse Show reverse dependencies with 'list-dependencies'\n"
@@ -6550,6 +6865,7 @@ static void systemctl_help(void) {
" -s --signal=SIGNAL Which signal to send\n"
" --now Start or stop unit in addition to enabling or disabling it\n"
" -q --quiet Suppress output\n"
+ " --wait For (re)start, wait until service stopped again\n"
" --no-block Do not wait until operation finished\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n"
" --no-reload Don't reload daemon after en-/dis-abling unit files\n"
@@ -6564,15 +6880,17 @@ static void systemctl_help(void) {
" --preset-mode= Apply only enable, only disable, or all presets\n"
" --root=PATH Enable unit files in the specified root directory\n"
" -n --lines=INTEGER Number of journal entries to show\n"
- " -o --output=STRING Change journal output mode (short, short-iso,\n"
- " short-precise, short-monotonic, verbose,\n"
- " export, json, json-pretty, json-sse, cat)\n"
+ " -o --output=STRING Change journal output mode (short, short-precise,\n"
+ " short-iso, short-full, short-monotonic, short-unix,\n"
+ " verbose, export, json, json-pretty, json-sse, cat)\n"
" --firmware-setup Tell the firmware to show the setup menu on next boot\n"
" --plain Print unit dependencies as a list instead of a tree\n\n"
"Unit Commands:\n"
- " list-units [PATTERN...] List loaded units\n"
- " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
- " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
+ " list-units [PATTERN...] List units currently in memory\n"
+ " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
+ " by address\n"
+ " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
+ " by next elapse\n"
" start NAME... Start (activate) one or more units\n"
" stop NAME... Stop (deactivate) one or more units\n"
" reload NAME... Reload one or more units\n"
@@ -6820,6 +7138,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_FIRMWARE_SETUP,
ARG_NOW,
ARG_MESSAGE,
+ ARG_WAIT,
};
static const struct option options[] = {
@@ -6843,6 +7162,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "global", no_argument, NULL, ARG_GLOBAL },
+ { "wait", no_argument, NULL, ARG_WAIT },
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
@@ -7023,6 +7343,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_scope = UNIT_FILE_GLOBAL;
break;
+ case ARG_WAIT:
+ arg_wait = true;
+ break;
+
case ARG_NO_BLOCK:
arg_no_block = true;
break;
@@ -7198,6 +7522,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
+ if (arg_wait && arg_no_block) {
+ log_error("--wait may not be combined with --no-block.");
+ return -EINVAL;
+ }
+
return 1;
}
diff --git a/src/grp-system/systemctl/systemctl.completion.bash.in b/src/grp-system/systemctl/systemctl.completion.bash.in
index 6f2b3f122c..dcf71a1f51 100644
--- a/src/grp-system/systemctl/systemctl.completion.bash.in
+++ b/src/grp-system/systemctl/systemctl.completion.bash.in
@@ -41,7 +41,7 @@ __contains_word () {
__filter_units_by_property () {
local mode=$1 property=$2 value=$3 ; shift 3
local units=("$@")
- local props
+ local props i
IFS=$'\n' read -rd '' -a props < \
<(__systemctl $mode show --property "$property" -- "${units[@]}")
for ((i=0; $i < ${#units[*]}; i++)); do
@@ -51,6 +51,33 @@ __filter_units_by_property () {
done
}
+__filter_units_by_properties () {
+ local mode=$1 properties=$2 values=$3 ; shift 3
+ local units=("$@")
+ local props i j conditions=()
+ IFS=$'\n' read -rd '' -a props < \
+ <(__systemctl $mode show --property "$properties" -- "${units[@]}")
+ IFS=$',' read -r -a properties < <(echo $properties)
+ IFS=$',' read -r -a values < <(echo $values)
+ for ((i=0; i < ${#properties[*]}; i++)); do
+ for ((j=0; j < ${#properties[*]}; j++)); do
+ if [[ ${props[i]%%=*} == ${properties[j]} ]]; then
+ conditions+=( "${properties[j]}=${values[j]}" )
+ fi
+ done
+ done
+ for ((i=0; i < ${#units[*]}; i++)); do
+ for ((j=0; j < ${#conditions[*]}; j++)); do
+ if [[ "${props[ i * ${#conditions[*]} + j]}" != "${conditions[j]}" ]]; then
+ break
+ fi
+ done
+ if (( j == ${#conditions[*]} )); then
+ echo " ${units[i]}"
+ fi
+ done
+}
+
__get_all_units () { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \
| { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; }
__get_template_names () { __systemctl $1 list-unit-files \
@@ -60,12 +87,12 @@ __get_active_units () { __systemctl $1 list-units \
| { while read -r a b; do echo " $a"; done; }; }
__get_startable_units () {
# find startable inactive units
- __filter_units_by_property $mode ActiveState inactive $(
- __filter_units_by_property $mode CanStart yes $(
- __systemctl $mode list-unit-files --state enabled,disabled,static | \
- { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }
- __systemctl $mode list-units --state inactive,failed | \
- { while read -r a b; do echo " $a"; done; } ))
+ __filter_units_by_properties $mode ActiveState,CanStart inactive,yes $(
+ { __systemctl $mode list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient | \
+ { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }
+ __systemctl $mode list-units --state inactive,failed | \
+ { while read -r a b c; do [[ $b == "loaded" ]] && echo " $a"; done; }
+ } | sort -u )
}
__get_restartable_units () {
# filter out masked and not-found
@@ -145,7 +172,7 @@ _systemctl () {
comps='full enable-only disable-only'
;;
--output|-o)
- comps='short short-iso short-precise short-monotonic verbose export json
+ comps='short short-full short-iso short-precise short-monotonic short-unix verbose export json
json-pretty json-sse cat'
;;
--machine|-M)
diff --git a/src/grp-system/systemctl/systemctl.completion.zsh.in b/src/grp-system/systemctl/systemctl.completion.zsh.in
index 44c31b7833..03a1c930b0 100644
--- a/src/grp-system/systemctl/systemctl.completion.zsh.in
+++ b/src/grp-system/systemctl/systemctl.completion.zsh.in
@@ -123,15 +123,11 @@ _systemctl_really_all_units()
}
_filter_units_by_property() {
- local property=$1 value=$2 ; shift ; shift
- local -a units ; units=($*)
- local props
- for props in ${(ps:\n\n:)"$(_call_program units "$service show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do
- props=(${(f)props})
- if [[ "${props[2]}" = "$property=$value" ]]; then
- echo -E - " ${props[1]#Id=}"
- fi
- done
+ local property=$1 value=$2; shift 2
+ local -a units; units=("${(q-)@}")
+ local -A props
+ props=(${(f)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property=\"Id,$property\" -- ${units} 2>/dev/null")"})
+ echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}"
}
_systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ }
@@ -351,8 +347,10 @@ _job_modes() {
_values -s , "${_modes[@]}"
}
+# Build arguments for "systemctl" to be used in completion.
local -a _modes; _modes=("--user" "--system")
-local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system}
+# Use the last mode (they are exclusive and the last one is used).
+local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]}
_arguments -s \
{-h,--help}'[Show help]' \
'--version[Show package version]' \
diff --git a/src/grp-system/systemctl/systemctl.xml b/src/grp-system/systemctl/systemctl.xml
index e7880d24f7..dfa00e0c03 100644
--- a/src/grp-system/systemctl/systemctl.xml
+++ b/src/grp-system/systemctl/systemctl.xml
@@ -156,6 +156,10 @@
<para>To list all units installed in the file system, use the
<command>list-unit-files</command> command instead.</para>
+
+ <para>When listing units with <command>list-dependencies</command>, recursively show
+ dependencies of all dependent units (by default only dependencies of target units are
+ shown).</para>
</listitem>
</varlistentry>
@@ -229,6 +233,8 @@
of <command>status</command>, <command>list-units</command>,
<command>list-jobs</command>, and
<command>list-timers</command>.</para>
+ <para>Also, show installation targets in the output of
+ <command>is-enabled</command>.</para>
</listitem>
</varlistentry>
@@ -302,7 +308,7 @@
<para><literal>ignore-requirements</literal> is similar to
<literal>ignore-dependencies</literal>, but only causes the
requirement dependencies to be ignored, the ordering
- dependencies will still be honoured.</para>
+ dependencies will still be honored.</para>
</listitem>
</varlistentry>
@@ -359,7 +365,20 @@
to finish. If this is not specified, the job will be
verified, enqueued and <command>systemctl</command> will
wait until the unit's start-up is completed. By passing this
- argument, it is only verified and enqueued.</para>
+ argument, it is only verified and enqueued. This option may not be
+ combined with <option>--wait</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--wait</option></term>
+
+ <listitem>
+ <para>Synchronously wait for started units to terminate again.
+ This option may not be combined with <option>--no-block</option>.
+ Note that this will wait forever if any given unit never terminates
+ (by itself or by getting stopped explicitly); particularly services
+ which use <literal>RemainAfterExit=yes</literal>.</para>
</listitem>
</varlistentry>
@@ -527,8 +546,10 @@
<listitem>
<para>When used with
<command>enable</command>/<command>disable</command>/<command>is-enabled</command>
- (and related commands), use an alternate root path when
- looking for unit files.</para>
+ (and related commands), use the specified root path when looking for unit
+ files. If this option is present, <command>systemctl</command> will operate on
+ the file system directly, instead of communicating with the <command>systemd</command>
+ daemon to carry out changes.</para>
</listitem>
</varlistentry>
@@ -609,7 +630,7 @@
<listitem>
<para>When used with <command>list-dependencies</command>,
- <command>list-units</command> or <command>list-machines</command>, the
+ <command>list-units</command> or <command>list-machines</command>,
the output is printed as a list instead of a tree, and the bullet
circles are omitted.</para>
</listitem>
@@ -638,13 +659,13 @@
<term><command>list-units <optional><replaceable>PATTERN</replaceable>...</optional></command></term>
<listitem>
- <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>List units that <command>systemd</command> currently has in memory. This includes units that are
+ either referenced directly or through a dependency, units that are pinned by applications programmatically,
+ 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>
@@ -654,9 +675,8 @@
<term><command>list-sockets <optional><replaceable>PATTERN</replaceable>...</optional></command></term>
<listitem>
- <para>List socket units ordered by listening address.
- If one or more <replaceable>PATTERN</replaceable>s are
- specified, only socket units matching one of them are
+ <para>List socket units currently in memory, ordered by listening address. If one or more
+ <replaceable>PATTERN</replaceable>s are specified, only socket units matching one of them are
shown. Produces output similar to
<programlisting>
LISTEN UNIT ACTIVATES
@@ -670,8 +690,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
is not suitable for programmatic consumption.
</para>
- <para>See also the options <option>--show-types</option>,
- <option>--all</option>, and <option>--state=</option>.</para>
+ <para>Also see <option>--show-types</option>, <option>--all</option>, and <option>--state=</option>.</para>
</listitem>
</varlistentry>
@@ -679,13 +698,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>list-timers <optional><replaceable>PATTERN</replaceable>...</optional></command></term>
<listitem>
- <para>List timer units ordered by the time they elapse
- next. If one or more <replaceable>PATTERN</replaceable>s
- are specified, only units matching one of them are shown.
+ <para>List timer units currently in memory, ordered by the time they elapse next. If one or more
+ <replaceable>PATTERN</replaceable>s are specified, only units matching one of them are shown.
</para>
- <para>See also the options <option>--all</option> and
- <option>--state=</option>.</para>
+ <para>Also see <option>--all</option> and <option>--state=</option>.</para>
</listitem>
</varlistentry>
@@ -696,8 +713,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<para>Start (activate) one or more units specified on the
command line.</para>
- <para>Note that glob patterns operate on the set of primary names of currently loaded units. Units which
- are not active and are not in a failed state usually are not loaded, and will not be matched by any
+ <para>Note that glob patterns operate on the set of primary names of units currently in memory. Units which
+ are not active and are not in a failed state usually are not in memory, and will not be matched by any
pattern. In addition, in case of instantiated units, systemd is often unaware of the instance name until
the instance has been started. Therefore, using glob patterns with <command>start</command> has limited
usefulness. Also, secondary alias names of units are not considered.</para>
@@ -860,8 +877,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<para>Show properties of one or more units, jobs, or the
manager itself. If no argument is specified, properties of
the manager will be shown. If a unit name is specified,
- properties of the unit is shown, and if a job ID is
- specified, properties of the job is shown. By default, empty
+ properties of the unit are shown, and if a job ID is
+ specified, properties of the job are shown. By default, empty
properties are suppressed. Use <option>--all</option> to
show those too. To select specific properties to show, use
<option>--property=</option>. This command is intended to be
@@ -877,7 +894,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<para>Show backing files of one or more units. Prints the
"fragment" and "drop-ins" (source files) of units. Each
file is preceded by a comment which includes the file
- name.</para>
+ name. Note that this shows the contents of the backing files
+ on disk, which may not match the system manager's
+ understanding of these units if any unit files were
+ updated on disk and the <command>daemon-reload</command>
+ command wasn't issued since.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -993,7 +1014,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
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
+ unit configuration directory, 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
@@ -1069,8 +1090,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<listitem>
<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>
+ enabled with to the defaults configured in its <literal>[Install]</literal> section. This command expects
+ a unit name only, it does not accept paths to unit files.</para>
</listitem>
</varlistentry>
@@ -1088,7 +1109,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
enabled and disabled, or only enabled, or only disabled.</para>
<para>If the unit carries no install information, it will be silently ignored
- by this command.</para>
+ by this command. <replaceable>NAME</replaceable> must be the real unit name,
+ any alias names are ignored silently.</para>
<para>For more information on the preset policy format, see
<citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
@@ -1120,6 +1142,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
exit code of 0 if at least one is enabled, non-zero
otherwise. Prints the current enable status (see table).
To suppress this output, use <option>--quiet</option>.
+ To show installation targets, use <option>--full</option>.
</para>
<table>
@@ -1242,7 +1265,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<literal>foo.service.d/</literal> with all their contained files are removed, both below the persistent and
runtime configuration directories (i.e. below <filename>/etc/systemd/system</filename> and
<filename>/run/systemd/system</filename>); if the unit file has a vendor-supplied version (i.e. a unit file
- located below <filename>/usr</filename>) any matching peristent or runtime unit file that overrides it is
+ located below <filename>/usr</filename>) any matching persistent or runtime unit file that overrides it is
removed, too. Note that if a unit file has no vendor-supplied version (i.e. is only defined below
<filename>/etc/systemd/system</filename> or <filename>/run/systemd/system</filename>, but not in a unit
file stored below <filename>/usr</filename>), then it is not removed. Also, if a unit is masked, it is
@@ -1676,20 +1699,15 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<term><command>switch-root <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></command></term>
<listitem>
- <para>Switches to a different root directory and executes a
- new system manager process below it. This is intended for
- usage in initial RAM disks ("initrd"), and will transition
- from the initrd's system manager process (a.k.a. "init"
- process) to the main system manager process. This call takes two
- arguments: the directory that is to become the new root directory, and
- the path to the new system manager binary below it to
- execute as PID 1. If the latter is omitted or the empty
- string, a systemd binary will automatically be searched for
- and used as init. If the system manager path is omitted or
- equal to the empty string, the state of the initrd's system
- manager process is passed to the main system manager, which
- allows later introspection of the state of the services
- involved in the initrd boot.</para>
+ <para>Switches to a different root directory and executes a new system manager process below it. This is
+ intended for usage in initial RAM disks ("initrd"), and will transition from the initrd's system manager
+ process (a.k.a. "init" process) to the main system manager process which is loaded from the actual host
+ volume. This call takes two arguments: the directory that is to become the new root directory, and the path
+ to the new system manager binary below it to execute as PID 1. If the latter is omitted or the empty
+ string, a systemd binary will automatically be searched for and used as init. If the system manager path is
+ omitted, equal to the empty string or identical to the path to the systemd binary, the state of the
+ initrd's system manager process is passed to the main system manager, which allows later introspection of
+ the state of the services involved in the initrd boot phase.</para>
</listitem>
</varlistentry>
@@ -1746,7 +1764,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
are equivalent to:
<programlisting># systemctl status dev-sda.device
# systemctl status home.mount</programlisting>
- In the second case, shell-style globs will be matched against the primary names of all currently loaded units;
+ In the second case, shell-style globs will be matched against the primary names of all units currently in memory;
literal unit names, with or without a suffix, will be treated as in the first case. This means that literal unit
names always refer to exactly one unit, but globs may match zero units and this is not considered an
error.</para>
@@ -1758,11 +1776,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<literal>[]</literal> may be used. See
<citerefentry project='man-pages'><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for more details. The patterns are matched against the primary names of
- currently loaded units, and patterns which do not match anything
+ units currently in memory, and patterns which do not match anything
are silently skipped. For example:
<programlisting># systemctl stop sshd@*.service</programlisting>
will stop all <filename>sshd@.service</filename> instances. Note that alias names of units, and units that aren't
- loaded are not considered for glob expansion.
+ in memory are not considered for glob expansion.
</para>
<para>For unit file commands, the specified <replaceable>NAME</replaceable> should be the name of the unit file
@@ -1804,6 +1822,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</variablelist>
<xi:include href="less-variables.xml" xpointer="pager"/>
<xi:include href="less-variables.xml" xpointer="less"/>
+ <xi:include href="less-variables.xml" xpointer="lesscharset"/>
</refsect1>
<refsect1>
diff --git a/src/grp-system/systemctl/systemd.preset.xml b/src/grp-system/systemctl/systemd.preset.xml
index b7164014f0..d09167baaf 100644
--- a/src/grp-system/systemctl/systemd.preset.xml
+++ b/src/grp-system/systemctl/systemd.preset.xml
@@ -98,6 +98,10 @@
Empty lines and lines whose first non-whitespace character is # or
; are ignored.</para>
+ <para>Presets must refer to the "real" unit file, and not to any aliases. See
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a description of unit aliasing.</para>
+
<para>Two different directives are understood:
<literal>enable</literal> may be used to enable units by default,
<literal>disable</literal> to disable units by default.</para>