From fb1bad9d51644f9db75f0aff7afc45610662756d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 18:16:28 +0200 Subject: man: document that "systemctl switch-root" tries hard to pass state across (#3995) As suggested: https://github.com/systemd/systemd/pull/3958#issuecomment-240410958 Let's document that we try hard to pass system state from the initrd to the host, and even compare the systemd binary paths. --- man/systemctl.xml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index 0ad0ad6d7e..9762fd0450 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1680,20 +1680,15 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service switch-root ROOT INIT - 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. + 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. -- cgit v1.2.3-54-g00ecf From 05a98afd3e0513de50c5949b7fa50ff0989d68bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 18:12:01 +0200 Subject: core: add Ref()/Unref() bus calls for units This adds two (privileged) bus calls Ref() and Unref() to the Unit interface. The two calls may be used by clients to pin a unit into memory, so that various runtime properties aren't flushed out by the automatic GC. This is necessary to permit clients to race-freely acquire runtime results (such as process exit status/code or accumulated CPU time) on successful service termination. Ref() and Unref() are fully recursive, hence act like the usual reference counting concept in C. Taking a reference is a privileged operation, as this allows pinning units into memory which consumes resources. Transient units may also gain a reference at the time of creation, via the new AddRef property (that is only defined for transient units at the time of creation). --- man/systemctl.xml | 12 +-- src/core/dbus-manager.c | 57 +++++++++++ src/core/dbus-unit.c | 155 +++++++++++++++++++++++++++++- src/core/dbus-unit.h | 8 +- src/core/dbus.c | 71 +++++++------- src/core/dbus.h | 5 +- src/core/job.c | 17 ++-- src/core/job.h | 4 +- src/core/manager.c | 27 +++--- src/core/org.freedesktop.systemd1.conf | 8 ++ src/core/unit.c | 52 +++++++--- src/core/unit.h | 7 ++ src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + 14 files changed, 341 insertions(+), 84 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index fde4f4f3bb..7e0ac9613a 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -642,13 +642,13 @@ list-units PATTERN... - List units that systemd 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 + List units that systemd has loaded. 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 . If one or more - PATTERNs are specified, only units matching one of them are - shown. The units that are shown are additionally filtered by - and if those options are specified. + PATTERNs are specified, only units matching one of them are shown. The units + that are shown are additionally filtered by and if those + options are specified. This is the default command. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ef05a75a8b..ea7ced2fd0 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -643,6 +643,54 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s return bus_unit_method_set_properties(message, u, error); } +static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_ref(message, u, error); +} + +static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_unref(message, u, error); +} + static int reply_unit_info(sd_bus_message *reply, Unit *u) { _cleanup_free_ char *unit_path = NULL, *job_path = NULL; Unit *following; @@ -781,6 +829,13 @@ static int transient_unit_from_message( if (r < 0) return r; + /* If the client asked for it, automatically add a reference to this unit. */ + if (u->bus_track_add) { + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return log_error_errno(r, "Failed to watch sender: %m"); + } + /* Now load the missing bits of the unit we just created */ unit_add_to_load_queue(u); manager_dispatch_load_queue(m); @@ -2211,6 +2266,8 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RefUnit", "s", NULL, method_ref_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnrefUnit", "s", NULL, method_unref_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 89e56a2e51..1b86bdde43 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -418,6 +418,7 @@ static int bus_verify_manage_units_async_full( const char *verb, int capability, const char *polkit_message, + bool interactive, sd_bus_message *call, sd_bus_error *error) { @@ -433,7 +434,15 @@ static int bus_verify_manage_units_async_full( details[7] = GETTEXT_PACKAGE; } - return bus_verify_polkit_async(call, capability, "org.freedesktop.systemd1.manage-units", details, false, UID_INVALID, &u->manager->polkit_registry, error); + return bus_verify_polkit_async( + call, + capability, + "org.freedesktop.systemd1.manage-units", + details, + interactive, + UID_INVALID, + &u->manager->polkit_registry, + error); } int bus_unit_method_start_generic( @@ -486,6 +495,7 @@ int bus_unit_method_start_generic( verb, CAP_SYS_ADMIN, job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL, + true, message, error); if (r < 0) @@ -558,6 +568,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * "kill", CAP_KILL, N_("Authentication is required to kill '$(unit)'."), + true, message, error); if (r < 0) @@ -588,6 +599,7 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus "reset-failed", CAP_SYS_ADMIN, N_("Authentication is required to reset the \"failed\" state of '$(unit)'."), + true, message, error); if (r < 0) @@ -620,6 +632,7 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b "set-property", CAP_SYS_ADMIN, N_("Authentication is required to set properties on '$(unit)'."), + true, message, error); if (r < 0) @@ -634,6 +647,53 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b return sd_bus_reply_method_return(message, NULL); } +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "start", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "ref", + CAP_SYS_ADMIN, + NULL, + false, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = bus_unit_track_remove_sender(u, message); + if (r == -EUNATCH) + return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_VTABLE_START(0), @@ -715,6 +775,8 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED), /* Obsolete properties or obsolete alias names */ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), @@ -1318,6 +1380,29 @@ static int bus_unit_set_transient_property( return r; return 1; + + } else if (streq(name, "AddRef")) { + + int b; + + /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method + * on the Unit interface, and it's probably not a good idea to expose a property and a method on the + * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for + * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference + * dependency type, hence let's not confuse things with that. + * + * Note that we don't acually add the reference to the bus track. We do that only after the setup of + * the transient unit is complete, so that setting this property multiple times in the same transient + * unit creation call doesn't count as individual references. */ + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) + u->bus_track_add = b; + + return 1; } return 0; @@ -1422,3 +1507,71 @@ int bus_unit_check_load_state(Unit *u, sd_bus_error *error) { return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id); } + +static int bus_track_handler(sd_bus_track *t, void *userdata) { + Unit *u = userdata; + + assert(t); + assert(u); + + u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */ + + unit_add_to_gc_queue(u); + return 0; +} + +static int allocate_bus_track(Unit *u) { + int r; + + assert(u); + + if (u->bus_track) + return 0; + + r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_track_handler, u); + if (r < 0) + return r; + + r = sd_bus_track_set_recursive(u->bus_track, true); + if (r < 0) { + u->bus_track = sd_bus_track_unref(u->bus_track); + return r; + } + + return 0; +} + +int bus_unit_track_add_name(Unit *u, const char *name) { + int r; + + assert(u); + + r = allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_name(u->bus_track, name); +} + +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) { + int r; + + assert(u); + + r = allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_sender(u->bus_track, m); +} + +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) { + assert(u); + + /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an + * error */ + if (!u->bus_track) + return -EUNATCH; + + return sd_bus_track_remove_sender(u->bus_track, m); +} diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 4db88dbebc..b280de7a1d 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -33,9 +33,15 @@ int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error); -int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error); int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_check_load_state(Unit *u, sd_bus_error *error); + +int bus_unit_track_add_name(Unit *u, const char *name); +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m); +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m); diff --git a/src/core/dbus.c b/src/core/dbus.c index 3422a02d68..1e41a42aa6 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1168,60 +1168,57 @@ int bus_foreach_bus( return ret; } -void bus_track_serialize(sd_bus_track *t, FILE *f) { +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { const char *n; assert(f); + assert(prefix); - for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) - fprintf(f, "subscribed=%s\n", n); -} - -int bus_track_deserialize_item(char ***l, const char *line) { - const char *e; - int r; - - assert(l); - assert(line); - - e = startswith(line, "subscribed="); - if (!e) - return 0; + for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) { + int c, j; - r = strv_extend(l, e); - if (r < 0) - return r; + c = sd_bus_track_count_name(t, n); - return 1; + for (j = 0; j < c; j++) { + fputs(prefix, f); + fputc('=', f); + fputs(n, f); + fputc('\n', f); + } + } } -int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) { +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) { + char **i; int r = 0; assert(m); assert(t); - assert(l); - - if (!strv_isempty(*l) && m->api_bus) { - char **i; - if (!*t) { - r = sd_bus_track_new(m->api_bus, t, NULL, NULL); - if (r < 0) - return r; - } + if (strv_isempty(l)) + return 0; - r = 0; - STRV_FOREACH(i, *l) { - int k; + if (!m->api_bus) + return 0; - k = sd_bus_track_add_name(*t, *i); - if (k < 0) - r = k; - } + if (!*t) { + r = sd_bus_track_new(m->api_bus, t, NULL, NULL); + if (r < 0) + return r; } - *l = strv_free(*l); + r = sd_bus_track_set_recursive(*t, recursive); + if (r < 0) + return r; + + r = 0; + STRV_FOREACH(i, l) { + int k; + + k = sd_bus_track_add_name(*t, *i); + if (k < 0) + r = k; + } return r; } diff --git a/src/core/dbus.h b/src/core/dbus.h index 6baaffbd75..a092ed9d76 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -28,9 +28,8 @@ void bus_done(Manager *m); int bus_fdset_add_all(Manager *m, FDSet *fds); -void bus_track_serialize(sd_bus_track *t, FILE *f); -int bus_track_deserialize_item(char ***l, const char *line); -int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l); +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l); int manager_sync_bus_names(Manager *m, sd_bus *bus); diff --git a/src/core/job.c b/src/core/job.c index 7557874d4d..7faf2ef686 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -997,7 +997,10 @@ char *job_dbus_path(Job *j) { return p; } -int job_serialize(Job *j, FILE *f, FDSet *fds) { +int job_serialize(Job *j, FILE *f) { + assert(j); + assert(f); + fprintf(f, "job-id=%u\n", j->id); fprintf(f, "job-type=%s\n", job_type_to_string(j->type)); fprintf(f, "job-state=%s\n", job_state_to_string(j->state)); @@ -1008,15 +1011,16 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) { if (j->begin_usec > 0) fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec); - bus_track_serialize(j->clients, f); + bus_track_serialize(j->clients, f, "subscribed"); /* End marker */ fputc('\n', f); return 0; } -int job_deserialize(Job *j, FILE *f, FDSet *fds) { +int job_deserialize(Job *j, FILE *f) { assert(j); + assert(f); for (;;) { char line[LINE_MAX], *l, *v; @@ -1106,7 +1110,7 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) { } else if (streq(l, "subscribed")) { if (strv_extend(&j->deserialized_clients, v) < 0) - return log_oom(); + log_oom(); } } } @@ -1118,9 +1122,8 @@ int job_coldplug(Job *j) { /* After deserialization is complete and the bus connection * set up again, let's start watching our subscribers again */ - r = bus_track_coldplug(j->manager, &j->clients, &j->deserialized_clients); - if (r < 0) - return r; + (void) bus_track_coldplug(j->manager, &j->clients, false, j->deserialized_clients); + j->deserialized_clients = strv_free(j->deserialized_clients); if (j->state == JOB_WAITING) job_add_to_run_queue(j); diff --git a/src/core/job.h b/src/core/job.h index d359e8bb3e..85368f0d30 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -177,8 +177,8 @@ Job* job_install(Job *j); int job_install_deserialized(Job *j); void job_uninstall(Job *j); void job_dump(Job *j, FILE*f, const char *prefix); -int job_serialize(Job *j, FILE *f, FDSet *fds); -int job_deserialize(Job *j, FILE *f, FDSet *fds); +int job_serialize(Job *j, FILE *f); +int job_deserialize(Job *j, FILE *f); int job_coldplug(Job *j); JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts); diff --git a/src/core/manager.c b/src/core/manager.c index 7576d038a2..b58f68fa7a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1287,10 +1287,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (q < 0 && r == 0) r = q; - /* We might have deserialized the kdbus control fd, but if we - * didn't, then let's create the bus now. */ - manager_connect_bus(m, !!serialization); - bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed); + /* We might have deserialized the kdbus control fd, but if we didn't, then let's create the bus now. */ + (void) manager_connect_bus(m, !!serialization); + + (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); /* Third, fire things up! */ manager_coldplug(m); @@ -2490,7 +2491,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "kdbus-fd=%i\n", copy); } - bus_track_serialize(m->subscribed, f); + bus_track_serialize(m->subscribed, f, "subscribed"); r = dynamic_user_serialize(m, f, fds); if (r < 0) @@ -2693,15 +2694,13 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { manager_deserialize_uid_refs_one(m, l + 16); else if (startswith(l, "destroy-ipc-gid=")) manager_deserialize_gid_refs_one(m, l + 16); - else { - int k; - - k = bus_track_deserialize_item(&m->deserialized_subscribed, l); - if (k < 0) - log_debug_errno(k, "Failed to deserialize bus tracker object: %m"); - else if (k == 0) - log_debug("Unknown serialization item '%s'", l); - } + else if (startswith(l, "subscribed=")) { + + if (strv_extend(&m->deserialized_subscribed, l+11) < 0) + log_oom(); + + } else + log_debug("Unknown serialization item '%s'", l); } for (;;) { diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 14f6aec029..647e5f736c 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -182,6 +182,14 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="Reexecute"/> + + + + diff --git a/src/core/unit.c b/src/core/unit.c index c58c501bc3..6d92eb0c30 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -329,6 +329,9 @@ bool unit_check_gc(Unit *u) { if (u->refs) return true; + if (sd_bus_track_count(u->bus_track) > 0) + return true; + if (UNIT_VTABLE(u)->check_gc) if (UNIT_VTABLE(u)->check_gc(u)) return true; @@ -509,6 +512,9 @@ void unit_free(Unit *u) { sd_bus_slot_unref(u->match_bus_slot); + sd_bus_track_unref(u->bus_track); + u->deserialized_refs = strv_free(u->deserialized_refs); + unit_free_requires_mounts_for(u); SET_FOREACH(t, u->names, i) @@ -897,6 +903,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { Unit *following; _cleanup_set_free_ Set *following_set = NULL; int r; + const char *n; assert(u); assert(u->type >= 0); @@ -1038,6 +1045,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { else if (u->load_state == UNIT_ERROR) fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error)); + for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track)) + fprintf(f, "%s\tBus Ref: %s\n", prefix, n); if (u->job) job_dump(u->job, f, prefix2); @@ -2622,15 +2631,17 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { if (gid_is_valid(u->ref_gid)) unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid); + bus_track_serialize(u->bus_track, f, "ref"); + if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); - job_serialize(u->job, f, fds); + job_serialize(u->job, f); } if (u->nop_job) { fprintf(f, "job\n"); - job_serialize(u->nop_job, f, fds); + job_serialize(u->nop_job, f); } } @@ -2760,7 +2771,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (!j) return log_oom(); - r = job_deserialize(j, f, fds); + r = job_deserialize(j, f); if (r < 0) { job_free(j); return r; @@ -2880,6 +2891,12 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { else unit_ref_uid_gid(u, UID_INVALID, gid); + } else if (streq(l, "ref")) { + + r = strv_extend(&u->deserialized_refs, v); + if (r < 0) + log_oom(); + continue; } @@ -2955,7 +2972,8 @@ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep } int unit_coldplug(Unit *u) { - int r = 0, q = 0; + int r = 0, q; + char **i; assert(u); @@ -2966,18 +2984,26 @@ int unit_coldplug(Unit *u) { u->coldplugged = true; - if (UNIT_VTABLE(u)->coldplug) - r = UNIT_VTABLE(u)->coldplug(u); + STRV_FOREACH(i, u->deserialized_refs) { + q = bus_unit_track_add_name(u, *i); + if (q < 0 && r >= 0) + r = q; + } + u->deserialized_refs = strv_free(u->deserialized_refs); - if (u->job) - q = job_coldplug(u->job); + if (UNIT_VTABLE(u)->coldplug) { + q = UNIT_VTABLE(u)->coldplug(u); + if (q < 0 && r >= 0) + r = q; + } - if (r < 0) - return r; - if (q < 0) - return q; + if (u->job) { + q = job_coldplug(u->job); + if (q < 0 && r >= 0) + r = q; + } - return 0; + return r; } static bool fragment_mtime_newer(const char *path, usec_t mtime) { diff --git a/src/core/unit.h b/src/core/unit.h index 53875653d7..e5a2a77b7b 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -108,6 +108,10 @@ struct Unit { /* The slot used for watching NameOwnerChanged signals */ sd_bus_slot *match_bus_slot; + /* References to this unit from clients */ + sd_bus_track *bus_track; + char **deserialized_refs; + /* Job timeout and action to take */ usec_t job_timeout; FailureAction job_timeout_action; @@ -247,6 +251,9 @@ struct Unit { /* Did we already invoke unit_coldplug() for this unit? */ bool coldplugged:1; + + /* For transient units: whether to add a bus track reference after creating the unit */ + bool bus_track_add:1; }; struct UnitStatusMessageFormats { diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 32be3cdc38..a69193aa32 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -45,6 +45,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index befb6fbfe0..5df21c8926 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -41,6 +41,7 @@ #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning" #define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser" +#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced" #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" -- cgit v1.2.3-54-g00ecf From d903a89246f40b6527e2358498657a9a3c625237 Mon Sep 17 00:00:00 2001 From: kristbaum Date: Thu, 15 Sep 2016 09:11:33 +0200 Subject: Update systemctl.xml (#4151) --- man/systemctl.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index 7e0ac9613a..781de0912a 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1073,8 +1073,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service Reenable one or more units, as specified on the command line. This is a combination of disable and enable and is useful to reset the symlinks a unit file is - enabled with to the defaults configured in its [Install] section. This commands expects - a unit uname only, it does not accept paths to unit files. + enabled with to the defaults configured in its [Install] section. This command expects + a unit name only, it does not accept paths to unit files. -- cgit v1.2.3-54-g00ecf From 831d3dc8d7ab2719c90485274b537f4a7882fe66 Mon Sep 17 00:00:00 2001 From: Alfie John <33c6c91f3bb4a391082e8a29642cafaf@alfie.wtf> Date: Wed, 28 Sep 2016 09:10:26 +0000 Subject: man: remove duplicate "the" for systemctl --plain (#4230) --- man/systemctl.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index 781de0912a..0bf9e1fd3f 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -613,7 +613,7 @@ When used with list-dependencies, - list-units or list-machines, the + list-units or list-machines, the output is printed as a list instead of a tree, and the bullet circles are omitted. -- cgit v1.2.3-54-g00ecf From 93a0884126146361ca078ec627da2cf766205a1c Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Mon, 5 Sep 2016 13:14:36 +0200 Subject: systemctl: Add --wait option to wait until started units terminate again Fixes #3830 --- man/systemctl.xml | 15 +++- src/systemctl/systemctl.c | 168 ++++++++++++++++++++++++++++++++++++++++- test/TEST-03-JOBS/test-jobs.sh | 28 +++++++ 3 files changed, 207 insertions(+), 4 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index 0bf9e1fd3f..e738b5aecd 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -363,7 +363,20 @@ to finish. If this is not specified, the job will be verified, enqueued and systemctl will wait until the unit's start-up is completed. By passing this - argument, it is only verified and enqueued. + argument, it is only verified and enqueued. This option may not be + combined with . + + + + + + + + Synchronously wait for started units to terminate again. + This option may not be combined with . + Note that this will wait forever if any given unit never terminates + (by itself or by getting stopped explicitly); particularly services + which use RemainAfterExit=yes. diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 5337561664..bb6002e8ef 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -118,6 +118,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; @@ -2679,13 +2680,86 @@ 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(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; + bool is_failed; + + r = sd_bus_message_read(m, "s", &s); + if (r < 0) + return bus_log_parse_error(r); + if (streq(s, "ActiveState")) { + 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); + set_remove(c->unit_paths, path); + 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; @@ -2696,6 +2770,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( @@ -2841,10 +2949,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 +3004,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 +3065,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; } @@ -6587,6 +6737,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" @@ -6857,6 +7008,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_FIRMWARE_SETUP, ARG_NOW, ARG_MESSAGE, + ARG_WAIT, }; static const struct option options[] = { @@ -6880,6 +7032,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 }, @@ -7060,6 +7213,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; @@ -7235,6 +7392,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/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh index 0c7d4439a2..fa6cf4181a 100755 --- a/test/TEST-03-JOBS/test-jobs.sh +++ b/test/TEST-03-JOBS/test-jobs.sh @@ -49,4 +49,32 @@ systemctl stop --job-mode=replace-irreversibly unstoppable.service || exit 1 # Shutdown of the container/VM will hang if not. systemctl start unstoppable.service || exit 1 +# Test waiting for a started unit(s) to terminate again +cat < /run/systemd/system/wait2.service +[Unit] +Description=Wait for 2 seconds +[Service] +ExecStart=/bin/sh -ec 'sleep 2' +EOF +cat < /run/systemd/system/wait5fail.service +[Unit] +Description=Wait for 5 seconds and fail +[Service] +ExecStart=/bin/sh -ec 'sleep 5; false' +EOF + +# wait2 succeeds +START_SEC=$(date -u '+%s') +systemctl start --wait wait2.service || exit 1 +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 2 ]] && [[ "$ELAPSED" -le 3 ]] || exit 1 + +# wait5fail fails, so systemctl should fail +START_SEC=$(date -u '+%s') +! systemctl start --wait wait2.service wait5fail.service || exit 1 +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 5 ]] && [[ "$ELAPSED" -le 7 ]] || exit 1 + touch /testok -- cgit v1.2.3-54-g00ecf From 6e16066e8ecd92e69b8f1e4bad728ee5b4cb7d34 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 17:45:49 +0200 Subject: man: expand the documentation of $SYSTEMD_PAGER and related environment variables Document the default pagers used, as well as $SYSTEMD_LESSCHARSET. Fixes: #4143 --- man/less-variables.xml | 53 ++++++++++++++++++++++++++++---------------------- man/systemctl.xml | 1 + 2 files changed, 31 insertions(+), 23 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/less-variables.xml b/man/less-variables.xml index 0fb4d7fbcf..1f34cbc1bf 100644 --- a/man/less-variables.xml +++ b/man/less-variables.xml @@ -3,27 +3,34 @@ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> - Environment - - - - $SYSTEMD_PAGER - - Pager to use when - is not given; - overrides $PAGER. Setting - this to an empty string or the value - cat is equivalent to passing - . - - - - $SYSTEMD_LESS - - Override the default - options passed to - less - (FRSXMK). - - + Environment + + + + $SYSTEMD_PAGER + + Pager to use when is not given; overrides + $PAGER. If neither $SYSTEMD_PAGER nor $PAGER are set, a + set of well-known pager implementations are tried in turn, including + less1 and + more1, until one is found. If + no pager implementation is discovered no pager is invoked. Setting this environment variable to an empty string + or the value cat is equivalent to passing . + + + + $SYSTEMD_LESS + + Override the options passed to less (by default + FRSXMK). + + + + $SYSTEMD_LESSCHARSET + + Override the charset passed to less (by default utf-8, if + the invoking terminal is determined to be UTF-8 compatible). + + + diff --git a/man/systemctl.xml b/man/systemctl.xml index e738b5aecd..cd1f3f976f 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1817,6 +1817,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service + -- cgit v1.2.3-54-g00ecf From 2cdbbc9a341eba4655ca03d13844fdc77753ce53 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 17:55:04 +0200 Subject: man: avoid using the term "loaded" for units currently in memory, since we also have a unit state of that name Fixes: #3971 --- man/systemctl.xml | 34 +++++++++++++++------------------- src/systemctl/systemctl.c | 14 ++++++++------ 2 files changed, 23 insertions(+), 25 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index cd1f3f976f..3b883ea754 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -655,10 +655,10 @@ list-units PATTERN... - List units that systemd has loaded. 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 . If one or more + List units that systemd 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 . If one or more PATTERNs are specified, only units matching one of them are shown. The units that are shown are additionally filtered by and if those options are specified. @@ -671,9 +671,8 @@ list-sockets PATTERN... - List socket units ordered by listening address. - If one or more PATTERNs are - specified, only socket units matching one of them are + List socket units currently in memory, ordered by listening address. If one or more + PATTERNs are specified, only socket units matching one of them are shown. Produces output similar to LISTEN UNIT ACTIVATES @@ -687,8 +686,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service is not suitable for programmatic consumption. - See also the options , - , and . + Also see , , and . @@ -696,13 +694,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service list-timers PATTERN... - List timer units ordered by the time they elapse - next. If one or more PATTERNs - are specified, only units matching one of them are shown. + List timer units currently in memory, ordered by the time they elapse next. If one or more + PATTERNs are specified, only units matching one of them are shown. - See also the options and - . + Also see and . @@ -713,8 +709,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service Start (activate) one or more units specified on the command line. - 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 + 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 start has limited usefulness. Also, secondary alias names of units are not considered. @@ -1759,7 +1755,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service are equivalent to: # systemctl status dev-sda.device # systemctl status home.mount - 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. @@ -1771,11 +1767,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service [] may be used. See glob7 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: # systemctl stop sshd@*.service will stop all sshd@.service 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. For unit file commands, the specified NAME should be the name of the unit file diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 18a8a4f248..7ed60dbe87 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6721,9 +6721,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" @@ -6758,9 +6758,11 @@ static void systemctl_help(void) { " --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" -- cgit v1.2.3-54-g00ecf From 2dd678171ee38cc48880a5437eeac7732426ad7d Mon Sep 17 00:00:00 2001 From: Thomas Hindoe Paaboel Andersen Date: Wed, 12 Oct 2016 23:02:44 +0200 Subject: man: typo fixes A mix of fixes for typos and UK english --- man/logind.conf.xml | 2 +- man/sd-event.xml | 2 +- man/sd_event_source_set_priority.xml | 2 +- man/systemctl.xml | 4 ++-- man/systemd-coredump.xml | 2 +- man/systemd-mount.xml | 2 +- man/systemd-nspawn.xml | 10 +++++----- man/systemd-run.xml | 2 +- man/systemd-system.conf.xml | 2 +- man/systemd.exec.xml | 4 ++-- man/systemd.link.xml | 2 +- man/systemd.socket.xml | 2 +- man/systemd.unit.xml | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 9b0e181849..994e0e1140 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -261,7 +261,7 @@ Controls whether actions that systemd-logind takes when the power and sleep keys and the lid switch are triggered are subject to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor - locks ("handle-*-key"), are always honoured, irrespective of this setting. + locks ("handle-*-key"), are always honored, irrespective of this setting. These settings take boolean arguments. If no, the inhibitor locks taken by applications are respected. If yes, diff --git a/man/sd-event.xml b/man/sd-event.xml index fc615f0906..24a69bb645 100644 --- a/man/sd-event.xml +++ b/man/sd-event.xml @@ -97,7 +97,7 @@ iteration a single event source is dispatched. Each time an event source is dispatched the kernel is polled for new events, before the next event source is dispatched. The event loop is designed to - honour priorities and provide fairness within each priority. It is + honor priorities and provide fairness within each priority. It is not designed to provide optimal throughput, as this contradicts these goals due the limitations of the underlying epoll7 diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml index 8c9b39fe5e..6e7032fc80 100644 --- a/man/sd_event_source_set_priority.xml +++ b/man/sd_event_source_set_priority.xml @@ -115,7 +115,7 @@ reliable. However, it is guaranteed that if events are seen on multiple same-priority event sources at the same time, each one is not dispatched again until all others have been dispatched - once. This behaviour guarantees that within each priority + once. This behavior guarantees that within each priority particular event sources do not starve or dominate the event loop. diff --git a/man/systemctl.xml b/man/systemctl.xml index 3b883ea754..b51badf7fe 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -306,7 +306,7 @@ ignore-requirements is similar to ignore-dependencies, but only causes the requirement dependencies to be ignored, the ordering - dependencies will still be honoured. + dependencies will still be honored. @@ -1006,7 +1006,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service desired, combine this command with the switch, or invoke start with appropriate arguments later. Note that in case of unit instance enablement (i.e. enablement of units of the form foo@bar.service), 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. This command expects either valid unit names (in which case various unit file directories are diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml index a28dc62e5a..4a1bc8b296 100644 --- a/man/systemd-coredump.xml +++ b/man/systemd-coredump.xml @@ -107,7 +107,7 @@ systemd-sysctl8. - The behaviour of systemd-coredump itself is configured through the configuration file + The behavior of systemd-coredump itself is configured through the configuration file /etc/systemd/coredump.conf and corresponding snippets /etc/systemd/coredump.conf.d/*.conf, see coredump.conf5. A new diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml index e6c07863c0..06b7c85bd8 100644 --- a/man/systemd-mount.xml +++ b/man/systemd-mount.xml @@ -260,7 +260,7 @@ The udev Database - If is used, systemd-mount honours a couple of additional udev + If is used, systemd-mount honors a couple of additional udev properties of block devices: diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 5ac54df81a..f153034296 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -405,7 +405,7 @@ purposes (usually in the range beyond the host's UID/GID 65536). The parameter may be specified as follows: - If one or two colon-separated numers are specified, user namespacing is turned on. The first + If one or two colon-separated numbers are specified, user namespacing is turned on. The first parameter specifies the first host UID/GID to assign to the container, the second parameter specifies the number of host UIDs/GIDs to assign to the container. If the second parameter is omitted, 65536 UIDs/GIDs are assigned. @@ -425,13 +425,13 @@ range is automatically chosen. As first step, the file owner of the root directory of the container's directory tree is read, and it is checked that it is currently not used by the system otherwise (in particular, that no other container is using it). If this check is successful, the UID/GID range determined - this way is used, similar to the behaviour if "yes" is specified. If the check is not successful (and thus + this way is used, similar to the behavior if "yes" is specified. If the check is not successful (and thus the UID/GID range indicated in the root directory's file owner is already used elsewhere) a new – currently unused – UID/GID range of 65536 UIDs/GIDs is randomly chosen between the host UID/GIDs of 524288 and 1878982656, always starting at a multiple of 65536. This setting implies (see below), which has the effect that the files and directories in the container's directory tree will be owned by the appropriate users of the range picked. Using this option - makes user namespace behaviour fully automatic. Note that the first invocation of a previously unused + makes user namespace behavior fully automatic. Note that the first invocation of a previously unused container image might result in picking a new UID/GID range for it, and thus in the (possibly expensive) file ownership adjustment operation. However, subsequent invocations of the container will be cheap (unless of course the picked UID/GID range is assigned to a different use by then). @@ -440,7 +440,7 @@ It is recommended to assign at least 65536 UIDs/GIDs to each container, so that the usable UID/GID range in the container covers 16 bit. For best security, do not assign overlapping UID/GID ranges to multiple containers. It is hence a good idea to use the upper 16 bit of the host 32-bit UIDs/GIDs as container identifier, while the lower 16 - bit encode the container UID/GID used. This is in fact the behaviour enforced by the + bit encode the container UID/GID used. This is in fact the behavior enforced by the option. When user namespaces are used, the GID range assigned to each container is always chosen identical to the @@ -722,7 +722,7 @@ and the subdirectory is symlinked into the host at the same location. try-host and try-guest do the same but do not fail if - the host does not have persistent journalling enabled. If + the host does not have persistent journaling enabled. If auto (the default), and the right subdirectory of /var/log/journal exists, it will be bind mounted into the container. If the diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 15f9119e54..2ad8cb0835 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -402,7 +402,7 @@ There is a screen on: when the user first logs in, and stays around as long as at least one login session is open. After the user logs out of the last session, user@.service and all services underneath it - are terminated. This behaviour is the default, when "lingering" is + are terminated. This behavior is the default, when "lingering" is not enabled for that user. Enabling lingering means that user@.service is started automatically during boot, even if the user is not logged in, and that the service is diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index a268397d09..1d995f143e 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -109,7 +109,7 @@ CtrlAltDelBurstAction= Defines what action will be performed - if user presses Ctr-Alt-Delete more than 7 times in 2s. + if user presses Ctrl-Alt-Delete more than 7 times in 2s. Can be set to reboot-force, poweroff-force or disabled with ignore. Defaults to reboot-force. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 986985ad35..c088042a51 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -988,7 +988,7 @@ the unit's own user and group to themselves and everything else to the nobody user and group. This is useful to securely detach the user and group databases used by the unit from the rest of the system, and thus to create an effective sandbox environment. All files, directories, processes, IPC objects and - other resources owned by users/groups not equalling root or the unit's own will stay visible + other resources owned by users/groups not equaling root or the unit's own will stay visible from within the unit but appear owned by the nobody user and group. If this mode is enabled, all unit processes are run without privileges in the host user namespace (regardless if the unit's own user/group is root or not). Specifically this means that the process will have zero process @@ -1560,7 +1560,7 @@ $MAINPID - The PID of the units main process if it is + The PID of the unit's main process if it is known. This is only set for control processes as invoked by ExecReload= and similar. diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 10fddeced0..8edbe758d9 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -107,7 +107,7 @@ A whitespace-separated list of shell-style globs matching the device name, as exposed by the udev property - "INTERFACE". This can not be used to match on names that have + "INTERFACE". This cannot be used to match on names that have already been changed from userspace. Caution is advised when matching on kernel-assigned names, as they are known to be unstable between reboots. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index d759e17289..0ce1203cfb 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -535,7 +535,7 @@ and the kernel will ignore initial ACK packets without any data. The argument specifies the approximate amount of time the kernel should wait for incoming data before falling back - to the normal behavior of honouring empty ACK packets. This + to the normal behavior of honoring empty ACK packets. This option is beneficial for protocols where the client sends the data first (e.g. HTTP, in contrast to SMTP), because the server process will not be woken up unnecessarily before it diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 9778283fec..79bdb2cd38 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -195,7 +195,7 @@ instantiated units, this logic will first look for the instance .d/ subdirectory and read its .conf files, followed by the template .d/ subdirectory and the .conf files there. Also note that - settings from the [Install] section are not honoured in drop-in unit files, + settings from the [Install] section are not honored in drop-in unit files, and have no effect. In addition to /etc/systemd/system, the drop-in .d -- cgit v1.2.3-54-g00ecf From 9b914a9d6b8279eecbf2c30f97e7aa6b21f03f5d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 19:44:40 -0400 Subject: man: mention that systemctl --root=/ operates on the fs directly --- man/systemctl.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index b51badf7fe..75885bcf02 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -544,8 +544,10 @@ When used with enable/disable/is-enabled - (and related commands), use an alternate root path when - looking for unit files. + (and related commands), use the specified root path when looking for unit + files. If this option is present, systemctl will operate on + the file system directly, instead of communicating with the systemd + daemon to carry out changes. -- cgit v1.2.3-54-g00ecf From 3b3557c410c7910fae0990599dcb82711cf5fbb7 Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Thu, 20 Oct 2016 15:20:11 +0200 Subject: shared, systemctl: teach is-enabled to show installation targets It may be desired by users to know what targets a particular service is installed into. Improve user friendliness by teaching the is-enabled command to show such information when used with --full. This patch makes use of the newly added UnitFileFlags and adds UNIT_FILE_DRY_RUN flag into it. Since the API had already been modified, it's now easy to add the new dry-run feature for other commands as well. As a next step, --dry-run could be added to systemctl, which in turn might pave the way for a long requested dry-run feature when running systemctl start. --- man/systemctl.xml | 3 ++ src/core/dbus-manager.c | 44 ++++++++++++++++++++ src/core/org.freedesktop.systemd1.conf | 4 ++ src/shared/install.c | 38 +++++++++-------- src/shared/install.h | 1 + src/systemctl/systemctl.c | 74 ++++++++++++++++++++++++++++++++-- 6 files changed, 145 insertions(+), 19 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index 75885bcf02..a4d4c53725 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -233,6 +233,8 @@ of status, list-units, list-jobs, and list-timers. + Also, show installation targets in the output of + is-enabled. @@ -1136,6 +1138,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 . + To show installation targets, use . diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ecad71a5aa..d7d3d3c8ce 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -2242,6 +2242,49 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } +static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + UnitFileChange *changes = NULL; + unsigned n_changes = 0, i; + UnitFileFlags flags; + const char *name; + char **p; + int runtime, r; + + r = sd_bus_message_read(message, "sb", &name, &runtime); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, "s"); + if (r < 0) + return r; + + p = STRV_MAKE(name); + flags = UNIT_FILE_DRY_RUN | + (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) { + r = sd_bus_message_append(reply, "s", changes[i].path); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_VTABLE_START(0), @@ -2387,6 +2430,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitFileLinks", "sb", "as", method_get_unit_file_links, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 6caa15b0b8..a61677e645 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -92,6 +92,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="GetUnitProcesses"/> + + diff --git a/src/shared/install.c b/src/shared/install.c index caca23435a..96fba6e25b 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -518,6 +518,7 @@ static int remove_marked_symlinks_fd( const char *path, const char *config_path, const LookupPaths *lp, + bool dry_run, bool *restart, UnitFileChange **changes, unsigned *n_changes) { @@ -566,7 +567,7 @@ static int remove_marked_symlinks_fd( } /* This will close nfd, regardless whether it succeeds or not */ - q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, restart, changes, n_changes); + q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, dry_run, restart, changes, n_changes); if (q < 0 && r == 0) r = q; @@ -603,14 +604,16 @@ static int remove_marked_symlinks_fd( if (!found) continue; - if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) { - if (r == 0) - r = -errno; - unit_file_changes_add(changes, n_changes, -errno, p, NULL); - continue; - } + if (!dry_run) { + if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) { + if (r == 0) + r = -errno; + unit_file_changes_add(changes, n_changes, -errno, p, NULL); + continue; + } - (void) rmdir_parents(p, config_path); + (void) rmdir_parents(p, config_path); + } unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); @@ -621,7 +624,7 @@ static int remove_marked_symlinks_fd( q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p); if (q < 0) return q; - if (q > 0) + if (q > 0 && !dry_run) *restart = true; } } @@ -633,6 +636,7 @@ static int remove_marked_symlinks( Set *remove_symlinks_to, const char *config_path, const LookupPaths *lp, + bool dry_run, UnitFileChange **changes, unsigned *n_changes) { @@ -659,7 +663,7 @@ static int remove_marked_symlinks( return -errno; /* This takes possession of cfd and closes it */ - q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, &restart, changes, n_changes); + q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, dry_run, &restart, changes, n_changes); if (r == 0) r = q; } while (restart); @@ -1861,6 +1865,7 @@ int unit_file_unmask( size_t n_todo = 0, n_allocated = 0; const char *config_path; char **i; + bool dry_run; int r, q; assert(scope >= 0); @@ -1871,6 +1876,7 @@ int unit_file_unmask( return r; config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + dry_run = !!(flags & UNIT_FILE_DRY_RUN); STRV_FOREACH(i, files) { _cleanup_free_ char *path = NULL; @@ -1907,7 +1913,7 @@ int unit_file_unmask( if (!path) return -ENOMEM; - if (unlink(path) < 0) { + if (!dry_run && unlink(path) < 0) { if (errno != ENOENT) { if (r >= 0) r = -errno; @@ -1925,7 +1931,7 @@ int unit_file_unmask( return q; } - q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes); + q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes); if (r >= 0) r = q; @@ -2175,11 +2181,11 @@ int unit_file_revert( return q; } - q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, changes, n_changes); + q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, false, changes, n_changes); if (r >= 0) r = q; - q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, changes, n_changes); + q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, false, changes, n_changes); if (r >= 0) r = q; @@ -2341,7 +2347,7 @@ int unit_file_disable( if (r < 0) return r; - return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes); + return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes); } int unit_file_reenable( @@ -2730,7 +2736,7 @@ static int execute_preset( if (r < 0) return r; - r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, changes, n_changes); + r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes); } else r = 0; diff --git a/src/shared/install.h b/src/shared/install.h index 561b521bbc..7a5859e729 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -82,6 +82,7 @@ enum UnitFileChangeType { enum UnitFileFlags { UNIT_FILE_RUNTIME = 1, UNIT_FILE_FORCE = 1 << 1, + UNIT_FILE_DRY_RUN = 1 << 2, }; /* type can either one of the UnitFileChangeTypes listed above, or a negative error. diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index c9ca3db3f1..2e3b59af3e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6271,6 +6271,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; @@ -6289,7 +6346,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; @@ -6305,8 +6361,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; @@ -6341,8 +6403,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; + } + } } } -- cgit v1.2.3-54-g00ecf From d4a48671bc453ead3cff911a0dfcc16ce5538072 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Wed, 26 Oct 2016 02:40:21 +0200 Subject: man: document that systemctl cat shows file content (#4488) ... and that that content might be outdated. --- man/systemctl.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index a4d4c53725..225eb06d8b 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -894,7 +894,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service 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. + 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 daemon-reload + command wasn't issued since. -- cgit v1.2.3-54-g00ecf From b17649ee5e9d620b752d17f783ea380b5111d060 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Mon, 31 Oct 2016 13:08:08 +0100 Subject: man: fix typos (#4527) --- man/machinectl.xml | 2 +- man/sd_journal_stream_fd.xml | 2 +- man/systemctl.xml | 2 +- man/systemd-machine-id-setup.xml | 4 ++-- man/systemd-socket-activate.xml | 2 +- man/systemd-system.conf.xml | 2 +- man/systemd.exec.xml | 4 ++-- man/systemd.offline-updates.xml | 2 +- man/systemd.target.xml | 2 +- man/tmpfiles.d.xml | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/machinectl.xml b/man/machinectl.xml index 0d57c01765..5a6ec294d2 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -188,7 +188,7 @@ When used with the shell command, chooses the user ID to open the interactive shell session as. If the argument to the shell - command also specifies an user name, this option is ignored. If the name is not specified + command also specifies a user name, this option is ignored. If the name is not specified in either way, root will be used by default. Note that this switch is not supported for the login command (see below). diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml index 226298ae1b..db88eba1bc 100644 --- a/man/sd_journal_stream_fd.xml +++ b/man/sd_journal_stream_fd.xml @@ -104,7 +104,7 @@ Notes - Function sd_journal_stream_fd() is thread-safe and may be be called + Function sd_journal_stream_fd() is thread-safe and may be called from multiple threads. All calls will return the same file descriptor, although temporarily multiple file descriptors may be open. diff --git a/man/systemctl.xml b/man/systemctl.xml index 225eb06d8b..ae3296d132 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1265,7 +1265,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service foo.service.d/ with all their contained files are removed, both below the persistent and runtime configuration directories (i.e. below /etc/systemd/system and /run/systemd/system); if the unit file has a vendor-supplied version (i.e. a unit file - located below /usr) any matching peristent or runtime unit file that overrides it is + located below /usr) 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 /etc/systemd/system or /run/systemd/system, but not in a unit file stored below /usr), then it is not removed. Also, if a unit is masked, it is diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml index 749987a937..944e899bd4 100644 --- a/man/systemd-machine-id-setup.xml +++ b/man/systemd-machine-id-setup.xml @@ -82,7 +82,7 @@ /etc/machine-id. If run inside a KVM virtual machine and a UUID - is was configured (via the + is configured (via the option), this UUID is used to initialize the machine ID. The caller must ensure that the UUID passed is sufficiently unique and is different for every booted instance of the @@ -154,7 +154,7 @@ - Print the machine ID generated or commited after the operation is complete. + Print the machine ID generated or committed after the operation is complete. diff --git a/man/systemd-socket-activate.xml b/man/systemd-socket-activate.xml index 2cf3a7d377..1c0619a840 100644 --- a/man/systemd-socket-activate.xml +++ b/man/systemd-socket-activate.xml @@ -142,7 +142,7 @@ FileDescriptorName= in socket unit files, and enables use of sd_listen_fds_with_names3. Multiple entries may be specifies using separate options or by separating names with colons - (:) in one option. In case more names are given than descriptors, superfluous ones willl be + (:) in one option. In case more names are given than descriptors, superfluous ones will be ignored. In case less names are given than descriptors, the remaining file descriptors will be unnamed. diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 80cad7f09c..e4e81f7f2e 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -330,7 +330,7 @@ TasksAccounting=. See systemd.resource-control5 for details on the per-unit - settings. DefaulTasksAccounting= defaults + settings. DefaultTasksAccounting= defaults to on, the other three settings to off. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 54ec7e29ca..d3a19c505d 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1090,7 +1090,7 @@ mechanism. Almost no services need to write to these at runtime; it is hence recommended to turn this on for most services. For this setting the same restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and related calls, see above. Defaults to off. - Note that this option does not prevent kernel tuning through IPC interfaces and exeternal programs. However + Note that this option does not prevent kernel tuning through IPC interfaces and external programs. However InaccessiblePaths= can be used to make some IPC file system objects inaccessible. @@ -1464,7 +1464,7 @@ Takes a boolean argument. If true, explicit module loading will be denied. This allows to turn off module load and unload operations on modular - kernels. It is recomended to turn this on for most services that do not need special + kernels. It is recommended to turn this on for most services that do not need special file systems or extra kernel modules to work. Default to off. Enabling this option removes CAP_SYS_MODULE from the capability bounding set for the unit, and installs a system call filter to block module system calls, diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml index f404c8d72f..07a5225512 100644 --- a/man/systemd.offline-updates.xml +++ b/man/systemd.offline-updates.xml @@ -143,7 +143,7 @@ FailureAction= makes sure that the specified unit is activated if your script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds you should trigger the reboot in your own code, for example by invoking logind's - Reboot() call or calling systemct reboot. See + Reboot() call or calling systemctl reboot. See logind dbus API for details. diff --git a/man/systemd.target.xml b/man/systemd.target.xml index 2e35e54fc4..b3cccd4e52 100644 --- a/man/systemd.target.xml +++ b/man/systemd.target.xml @@ -83,7 +83,7 @@ Automatic Dependencies Unless DefaultDependencies= is set to - in either of releated units or an explicit ordering + in either of related units or an explicit ordering dependency is already defined, target units will implicitly complement all configured dependencies of type Wants= or Requires= with dependencies of type diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 75fb901102..e040a1636d 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -644,7 +644,7 @@ d /run/uscreens 0755 root screen 10d12h t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar" - The direcory will be owned by root and have default mode. It's contents are + The directory will be owned by root and have default mode. Its contents are not subject to time based cleanup, but will be obliterated when systemd-tmpfiles --remove runs. -- cgit v1.2.3-54-g00ecf From 0cc6064c3c2ea8e61298ff3b4a49ad63461db9ea Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Thu, 3 Nov 2016 01:10:29 +0100 Subject: man: fix two typos (is → are) (#4544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- man/systemctl.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'man/systemctl.xml') diff --git a/man/systemctl.xml b/man/systemctl.xml index ae3296d132..dfa00e0c03 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -877,8 +877,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service 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 to show those too. To select specific properties to show, use . This command is intended to be -- cgit v1.2.3-54-g00ecf