mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
units: introduce new Documentation= field and make use of it everywhere
This should help making the boot process a bit easier to explore and understand for the administrator. The simple idea is that "systemctl status" now shows a link to documentation alongside the other status and decriptionary information of a service. This patch adds the necessary fields to all our shipped units if we have proper documentation for them.
This commit is contained in:
@@ -49,7 +49,9 @@
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>basic.target</filename>,
|
||||
<filename>bluetooth.target</filename>,
|
||||
<filename>ctrl-alt-del.target</filename>,
|
||||
<filename>cryptsetup.target</filename>,
|
||||
<filename>dbus.service</filename>,
|
||||
<filename>dbus.socket</filename>,
|
||||
<filename>default.target</filename>,
|
||||
@@ -57,6 +59,7 @@
|
||||
<filename>emergency.target</filename>,
|
||||
<filename>exit.service</filename>,
|
||||
<filename>final.service</filename>,
|
||||
<filename>getty.target</filename>,
|
||||
<filename>graphical.target</filename>,
|
||||
<filename>hibernate.target</filename>,
|
||||
<filename>http-daemon.target</filename>,
|
||||
@@ -69,7 +72,9 @@
|
||||
<filename>multi-user.target</filename>,
|
||||
<filename>network.target</filename>,
|
||||
<filename>nss-lookup.target</filename>,
|
||||
<filename>nss-user-lookup.target</filename>,
|
||||
<filename>poweroff.target</filename>,
|
||||
<filename>printer.target</filename>,
|
||||
<filename>reboot.target</filename>,
|
||||
<filename>remote-fs.target</filename>,
|
||||
<filename>remote-fs-pre.target</filename>,
|
||||
@@ -82,7 +87,9 @@
|
||||
<filename>shutdown.target</filename>,
|
||||
<filename>sigpwr.target</filename>,
|
||||
<filename>sleep.target</filename>,
|
||||
<filename>smartcard.target</filename>,
|
||||
<filename>sockets.target</filename>,
|
||||
<filename>sound.target</filename>,
|
||||
<filename>suspend.target</filename>,
|
||||
<filename>swap.target</filename>,
|
||||
<filename>sysinit.target</filename>,
|
||||
@@ -127,6 +134,16 @@
|
||||
this unit.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>bluetooth.target</filename></term>
|
||||
<listitem>
|
||||
<para>This target is started
|
||||
automatically as soon as a
|
||||
bluetooth controller is
|
||||
plugged in or becomes
|
||||
available at boot.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>ctrl-alt-del.target</filename></term>
|
||||
<listitem>
|
||||
@@ -139,6 +156,15 @@
|
||||
<filename>reboot.target</filename>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>cryptsetup.target</filename></term>
|
||||
<listitem>
|
||||
<para>A target that pulls in
|
||||
setup services for all
|
||||
encrypted block
|
||||
devices.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>dbus.service</filename></term>
|
||||
<listitem>
|
||||
@@ -226,6 +252,15 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>getty.target</filename></term>
|
||||
<listitem>
|
||||
<para>A special target unit
|
||||
that pulls in all local TTY
|
||||
<filename>getty</filename> instances.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>graphical.target</filename></term>
|
||||
<listitem>
|
||||
@@ -442,6 +477,16 @@
|
||||
unit, for compatibility with SysV.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>printer.target</filename></term>
|
||||
<listitem>
|
||||
<para>This target is started
|
||||
automatically as soon as a
|
||||
printer is plugged in or
|
||||
becomes available at
|
||||
boot.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>reboot.target</filename></term>
|
||||
<listitem>
|
||||
@@ -615,6 +660,16 @@
|
||||
logic.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>smartcard.target</filename></term>
|
||||
<listitem>
|
||||
<para>This target is started
|
||||
automatically as soon as a
|
||||
smartcard controller is
|
||||
plugged in or becomes
|
||||
available at boot.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>sockets.target</filename></term>
|
||||
<listitem>
|
||||
@@ -629,6 +684,16 @@
|
||||
during installation.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>sound.target</filename></term>
|
||||
<listitem>
|
||||
<para>This target is started
|
||||
automatically as soon as a
|
||||
sound card is plugged in or
|
||||
becomes available at
|
||||
boot.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>suspend.target</filename></term>
|
||||
<listitem>
|
||||
|
||||
@@ -294,6 +294,23 @@
|
||||
name.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Documentation=</varname></term>
|
||||
<listitem><para>A space separated list
|
||||
of URIs referencing documentation for
|
||||
this unit or its
|
||||
configuration. Accepted are only URIs
|
||||
of the types
|
||||
<literal>http://</literal>,
|
||||
<literal>https://</literal>,
|
||||
<literal>file:</literal>,
|
||||
<literal>info:</literal>,
|
||||
<literal>man:</literal>. For more
|
||||
information about the syntax of these
|
||||
URIs see
|
||||
<citerefentry><refentrytitle>uri</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Requires=</varname></term>
|
||||
|
||||
|
||||
@@ -808,6 +808,7 @@ const BusProperty bus_unit_properties[] = {
|
||||
{ "PropagateReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_TO]), true },
|
||||
{ "PropagateReloadFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_FROM]), true },
|
||||
{ "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
|
||||
{ "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
|
||||
{ "Description", bus_unit_append_description, "s", 0 },
|
||||
{ "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
|
||||
{ "ActiveState", bus_unit_append_active_state, "s", 0 },
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
" <property name=\"PropagateReloadFrom\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"SubState\" type=\"s\" access=\"read\"/>\n" \
|
||||
|
||||
@@ -92,6 +92,7 @@ $1.ControlGroupPersistent, config_parse_tristate, 0,
|
||||
)m4_dnl
|
||||
Unit.Names, config_parse_unit_names, 0, 0
|
||||
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
|
||||
Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
|
||||
Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
|
||||
Unit.RequiresOverridable, config_parse_unit_deps, UNIT_REQUIRES_OVERRIDABLE, 0
|
||||
Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
|
||||
|
||||
@@ -2063,6 +2063,43 @@ int config_parse_unit_requires_mounts_for(
|
||||
return r;
|
||||
}
|
||||
|
||||
int config_parse_documentation(
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Unit *u = userdata;
|
||||
int r;
|
||||
char **a, **b;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(u);
|
||||
|
||||
r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (a = b = u->documentation; a && *a; a++) {
|
||||
|
||||
if (is_valid_documentation_url(*a))
|
||||
*(b++) = *a;
|
||||
else {
|
||||
log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
|
||||
free(*a);
|
||||
}
|
||||
}
|
||||
*b = NULL;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#define FOLLOW_MAX 8
|
||||
|
||||
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
|
||||
|
||||
@@ -36,6 +36,7 @@ int config_parse_unit_names(const char *filename, unsigned line, const char *sec
|
||||
int config_parse_unit_string_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_strv_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_path_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_documentation(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_socket_listen(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_socket_bind(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_exec_nice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
@@ -397,6 +397,7 @@ void unit_free(Unit *u) {
|
||||
cgroup_attribute_free_list(u->cgroup_attributes);
|
||||
|
||||
free(u->description);
|
||||
strv_free(u->documentation);
|
||||
free(u->fragment_path);
|
||||
free(u->instance);
|
||||
|
||||
@@ -624,7 +625,7 @@ const char *unit_description(Unit *u) {
|
||||
}
|
||||
|
||||
void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
char *t;
|
||||
char *t, **j;
|
||||
UnitDependency d;
|
||||
Iterator i;
|
||||
char *p2;
|
||||
@@ -672,6 +673,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
SET_FOREACH(t, u->names, i)
|
||||
fprintf(f, "%s\tName: %s\n", prefix, t);
|
||||
|
||||
STRV_FOREACH(j, u->documentation)
|
||||
fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
|
||||
|
||||
if ((following = unit_following(u)))
|
||||
fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
|
||||
|
||||
@@ -698,8 +702,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
}
|
||||
|
||||
if (!strv_isempty(u->requires_mounts_for)) {
|
||||
char **j;
|
||||
|
||||
fprintf(f,
|
||||
"%s\tRequiresMountsFor:", prefix);
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ struct Unit {
|
||||
char **requires_mounts_for;
|
||||
|
||||
char *description;
|
||||
char **documentation;
|
||||
|
||||
char *fragment_path; /* if loaded from a config file this is the primary path to it */
|
||||
usec_t fragment_mtime;
|
||||
|
||||
@@ -5610,3 +5610,24 @@ int can_sleep(const char *type) {
|
||||
free(p);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool is_valid_documentation_url(const char *url) {
|
||||
assert(url);
|
||||
|
||||
if (startswith(url, "http://") && url[7])
|
||||
return true;
|
||||
|
||||
if (startswith(url, "https://") && url[8])
|
||||
return true;
|
||||
|
||||
if (startswith(url, "file:") && url[5])
|
||||
return true;
|
||||
|
||||
if (startswith(url, "info:") && url[5])
|
||||
return true;
|
||||
|
||||
if (startswith(url, "man:") && url[4])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -508,4 +508,6 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value);
|
||||
|
||||
int can_sleep(const char *type);
|
||||
|
||||
bool is_valid_documentation_url(const char *url);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2158,6 +2158,8 @@ typedef struct UnitStatusInfo {
|
||||
const char *description;
|
||||
const char *following;
|
||||
|
||||
char **documentation;
|
||||
|
||||
const char *path;
|
||||
const char *default_control_group;
|
||||
|
||||
@@ -2303,6 +2305,19 @@ static void print_status_info(UnitStatusInfo *i) {
|
||||
if (i->what)
|
||||
printf("\t What: %s\n", i->what);
|
||||
|
||||
if (!strv_isempty(i->documentation)) {
|
||||
char **t;
|
||||
bool first = true;
|
||||
|
||||
STRV_FOREACH(t, i->documentation) {
|
||||
if (first) {
|
||||
printf("\t Docs: %s\n", *t);
|
||||
first = false;
|
||||
} else
|
||||
printf("\t %s\n", *t);
|
||||
}
|
||||
}
|
||||
|
||||
if (i->accept)
|
||||
printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
|
||||
|
||||
@@ -2607,6 +2622,27 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
|
||||
|
||||
LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
|
||||
|
||||
dbus_message_iter_next(&sub);
|
||||
}
|
||||
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
|
||||
streq(name, "Documentation")) {
|
||||
|
||||
DBusMessageIter sub;
|
||||
|
||||
dbus_message_iter_recurse(iter, &sub);
|
||||
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
|
||||
const char *s;
|
||||
char **l;
|
||||
|
||||
dbus_message_iter_get_basic(&sub, &s);
|
||||
|
||||
l = strv_append(i->documentation, s);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
strv_free(i->documentation);
|
||||
i->documentation = l;
|
||||
|
||||
dbus_message_iter_next(&sub);
|
||||
}
|
||||
}
|
||||
@@ -2932,6 +2968,8 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
|
||||
if (!show_properties)
|
||||
print_status_info(&info);
|
||||
|
||||
strv_free(info.documentation);
|
||||
|
||||
if (!streq_ptr(info.active_state, "active") &&
|
||||
!streq_ptr(info.active_state, "reloading") &&
|
||||
streq(verb, "status"))
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# See systemd.special(7) for details
|
||||
|
||||
[Unit]
|
||||
Description=Basic System
|
||||
Documentation=man:systemd.special(7)
|
||||
Requires=sysinit.target sockets.target
|
||||
After=sysinit.target sockets.target
|
||||
RefuseManualStart=yes
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# See systemd.special(7) for details
|
||||
|
||||
[Unit]
|
||||
Description=Bluetooth
|
||||
Documentation=man:systemd.special(7)
|
||||
StopWhenUnneeded=yes
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# See systemd.special(7) for details
|
||||
|
||||
[Unit]
|
||||
Description=Encrypted Volumes
|
||||
Documentation=man:systemd.special(7)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
[Unit]
|
||||
Description=Huge Pages File System
|
||||
Documentation=https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
|
||||
DefaultDependencies=no
|
||||
Before=sysinit.target
|
||||
ConditionPathExists=/sys/kernel/mm/hugepages
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
[Unit]
|
||||
Description=POSIX Message Queue File System
|
||||
Documentation=man:mq_overview(7)
|
||||
DefaultDependencies=no
|
||||
Before=sysinit.target
|
||||
ConditionPathExists=/proc/sys/fs/mqueue
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# See systemd.special(7) for details
|
||||
|
||||
[Unit]
|
||||
Description=Emergency Shell
|
||||
DefaultDependencies=no
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# See systemd.special(7) for details
|
||||
|
||||
[Unit]
|
||||
Description=Emergency Mode
|
||||
Documentation=man:systemd.special(7)
|
||||
Requires=emergency.service
|
||||
After=emergency.service
|
||||
AllowIsolate=yes
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# See systemd.special(7) for details
|
||||
|
||||
[Unit]
|
||||
Description=Final Step
|
||||
Documentation=man:systemd.special(7)
|
||||
DefaultDependencies=no
|
||||
RefuseManualStart=yes
|
||||
After=shutdown.target umount.target
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user