diff options
-rw-r--r-- | man/systemd.unit.xml | 284 | ||||
-rw-r--r-- | src/core/load-dropin.c | 63 | ||||
-rw-r--r-- | src/core/unit.c | 20 |
3 files changed, 207 insertions, 160 deletions
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 54671e7f19..bba0f5d29f 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -81,7 +81,7 @@ sections of the unit files.</para> <para>In addition to the generic [Unit] and [Install] - sections described here, each unit should have a + sections described here, each unit may have a type-specific section, e.g. [Service] for a service unit. See the respective man pages for more information.</para> @@ -106,12 +106,14 @@ <para>Time span values encoded in unit files can be written in various formats. A stand-alone number specifies a time in seconds. If suffixed with a time - unit, the unit is honored. A concatenation of - multiple values with units is supported, in which case - the values are added up. Example: "50" refers to 50 + unit, the unit is honored. A concatenation of multiple + values with units is supported, in which case the + values are added up. Example: "50" refers to 50 seconds; "2min 200ms" refers to 2 minutes plus 200 milliseconds, i.e. 120200ms. The following time units - are understood: s, min, h, d, w, ms, us. For details see <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para> + are understood: s, min, h, d, w, ms, us. For details + see + <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para> <para>Empty lines and lines starting with # or ; are ignored. This may be used for commenting. Lines ending @@ -119,32 +121,42 @@ line while reading and the backslash is replaced by a space character. This may be used to wrap long lines.</para> - <para>If a line starts with <option>.include</option> - followed by a file name, the specified file will be - parsed at this point. Make sure that the file that is - included has the appropriate section headers before - any directives.</para> - <para>Along with a unit file - <filename>foo.service</filename> a directory + <filename>foo.service</filename> the directory <filename>foo.service.wants/</filename> may exist. All - units symlinked from such a directory are implicitly - added as dependencies of type + unit files symlinked from such a directory are + implicitly added as dependencies of type <varname>Wanted=</varname> to the unit. This is useful to hook units into the start-up of other units, - without having to modify their unit configuration - files. For details about the semantics of - <varname>Wanted=</varname> see below. The preferred - way to create symlinks in the - <filename>.wants/</filename> directory of a service is - with the <command>enable</command> command of the + without having to modify their unit files. For details + about the semantics of <varname>Wanted=</varname> see + below. The preferred way to create symlinks in the + <filename>.wants/</filename> directory of a unit file + is with the <command>enable</command> command of the <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> tool which reads information from the [Install] - section of unit files. (See below.) A similar + section of unit files (see below). A similar functionality exists for <varname>Requires=</varname> type dependencies as well, the directory suffix is <filename>.requires/</filename> in this case.</para> + <para>Along with a unit file + <filename>foo.service</filename> a directory + <filename>foo.service.d/</filename> may exist. All + files with the suffix <filename>.conf</filename> from + this directory will be parsed after the file itself is + parsed. This is useful to alter or add configuration + settings to a unit, without having to modify their + unit files. Make sure that the file that is included + has the appropriate section headers before any + directive.</para> + + <para>If a line starts with <option>.include</option> + followed by a file name, the specified file will be + parsed at this point. Make sure that the file that is + included has the appropriate section headers before + any directives.</para> + <para>Note that while systemd offers a flexible dependency system between units it is recommended to use this functionality only sparsely and instead rely @@ -186,116 +198,7 @@ <para>To refer to the instance string from within the configuration file you may use the special <literal>%i</literal> specifier in many of the - configuration options. Other specifiers exist, the - full list is:</para> - - <table> - <title>Specifiers available in unit files</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colname="spec" /> - <colspec colname="mean" /> - <colspec colname="detail" /> - <thead> - <row> - <entry>Specifier</entry> - <entry>Meaning</entry> - <entry>Details</entry> - </row> - </thead> - <tbody> - <row> - <entry><literal>%n</literal></entry> - <entry>Full unit name</entry> - <entry></entry> - </row> - <row> - <entry><literal>%N</literal></entry> - <entry>Unescaped full unit name</entry> - <entry></entry> - </row> - <row> - <entry><literal>%p</literal></entry> - <entry>Prefix name</entry> - <entry>This refers to the string before the @, i.e. "getty" in the example above, where "tty3" is the instance name.</entry> - </row> - <row> - <entry><literal>%P</literal></entry> - <entry>Unescaped prefix name</entry> - <entry></entry> - </row> - <row> - <entry><literal>%i</literal></entry> - <entry>Instance name</entry> - <entry>This is the string between the @ character and the suffix.</entry> - </row> - <row> - <entry><literal>%I</literal></entry> - <entry>Unescaped instance name</entry> - <entry></entry> - </row> - <row> - <entry><literal>%f</literal></entry> - <entry>Unescaped file name</entry> - <entry>This is either the unescaped instance name (if set) with / prepended (if necessary), or the prefix name similarly prepended with /.</entry> - </row> - <row> - <entry><literal>%c</literal></entry> - <entry>Control group path of the unit</entry> - <entry></entry> - </row> - <row> - <entry><literal>%r</literal></entry> - <entry>Root control group path of systemd</entry> - <entry></entry> - </row> - <row> - <entry><literal>%R</literal></entry> - <entry>Parent directory of the root control group path of systemd</entry> - <entry></entry> - </row> - <row> - <entry><literal>%t</literal></entry> - <entry>Runtime socket dir</entry> - <entry>This is either /run (for the system manager) or $XDG_RUNTIME_DIR (for user managers).</entry> - </row> - <row> - <entry><literal>%u</literal></entry> - <entry>User name</entry> - <entry>This is the name of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> - </row> - <row> - <entry><literal>%U</literal></entry> - <entry>User uid</entry> - <entry>This is the uid of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> - </row> - <row> - <entry><literal>%h</literal></entry> - <entry>User home directory</entry> - <entry>This is the home directory of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> - </row> - <row> - <entry><literal>%s</literal></entry> - <entry>User shell</entry> - <entry>This is the shell of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> - </row> - <row> - <entry><literal>%m</literal></entry> - <entry>Machine ID</entry> - <entry>The machine ID of the running system, formatted as string. See <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry> - </row> - <row> - <entry><literal>%b</literal></entry> - <entry>Boot ID</entry> - <entry>The boot ID of the running system, formatted as string. See <citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry> for more information.</entry> - </row> - <row> - <entry><literal>%H</literal></entry> - <entry>Host name</entry> - <entry>The host name of the running system.</entry> - </row> - </tbody> - </tgroup> - </table> + configuration options. See below for details.</para> <para>If a unit file is empty (i.e. has the file size 0) or is symlinked to <filename>/dev/null</filename> @@ -309,6 +212,7 @@ <ulink url="http://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise">Interface Stability Promise</ulink>.</para> + </refsect1> <refsect1> @@ -1085,6 +989,124 @@ </refsect1> <refsect1> + <title>Specifiers</title> + + <para>Many settings resolve specifiers which may be + used to write generic unit files referring to runtime + or unit parameters that are replaced when the unit + files are loaded. The following specifiers are + understood:</para> + + <table> + <title>Specifiers available in unit files</title> + <tgroup cols='3' align='left' colsep='1' rowsep='1'> + <colspec colname="spec" /> + <colspec colname="mean" /> + <colspec colname="detail" /> + <thead> + <row> + <entry>Specifier</entry> + <entry>Meaning</entry> + <entry>Details</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>%n</literal></entry> + <entry>Full unit name</entry> + <entry></entry> + </row> + <row> + <entry><literal>%N</literal></entry> + <entry>Unescaped full unit name</entry> + <entry></entry> + </row> + <row> + <entry><literal>%p</literal></entry> + <entry>Prefix name</entry> + <entry>For instantiated units this refers to the string before the @. For non-instantiated units this refers to to the name of the unit with the type suffix removed.</entry> + </row> + <row> + <entry><literal>%P</literal></entry> + <entry>Unescaped prefix name</entry> + <entry></entry> + </row> + <row> + <entry><literal>%i</literal></entry> + <entry>Instance name</entry> + <entry>For instantiated units: this is the string between the @ character and the suffix.</entry> + </row> + <row> + <entry><literal>%I</literal></entry> + <entry>Unescaped instance name</entry> + <entry></entry> + </row> + <row> + <entry><literal>%f</literal></entry> + <entry>Unescaped file name</entry> + <entry>This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the prefix name similarly prepended with /.</entry> + </row> + <row> + <entry><literal>%c</literal></entry> + <entry>Control group path of the unit</entry> + <entry></entry> + </row> + <row> + <entry><literal>%r</literal></entry> + <entry>Root control group path of systemd</entry> + <entry></entry> + </row> + <row> + <entry><literal>%R</literal></entry> + <entry>Parent directory of the root control group path of systemd</entry> + <entry></entry> + </row> + <row> + <entry><literal>%t</literal></entry> + <entry>Runtime socket dir</entry> + <entry>This is either <filename>/run</filename> (for the system manager) or <literal>$XDG_RUNTIME_DIR</literal> (for user managers).</entry> + </row> + <row> + <entry><literal>%u</literal></entry> + <entry>User name</entry> + <entry>This is the name of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> + </row> + <row> + <entry><literal>%U</literal></entry> + <entry>User UID</entry> + <entry>This is the UID of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> + </row> + <row> + <entry><literal>%h</literal></entry> + <entry>User home directory</entry> + <entry>This is the home directory of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> + </row> + <row> + <entry><literal>%s</literal></entry> + <entry>User shell</entry> + <entry>This is the shell of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry> + </row> + <row> + <entry><literal>%m</literal></entry> + <entry>Machine ID</entry> + <entry>The machine ID of the running system, formatted as string. See <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry> + </row> + <row> + <entry><literal>%b</literal></entry> + <entry>Boot ID</entry> + <entry>The boot ID of the running system, formatted as string. See <citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry> for more information.</entry> + </row> + <row> + <entry><literal>%H</literal></entry> + <entry>Host name</entry> + <entry>The host name of the running system.</entry> + </row> + </tbody> + </tgroup> + </table> + </refsect1> + + <refsect1> <title>See Also</title> <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index 86f81c7484..8e10d8fb4c 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -27,10 +27,21 @@ #include "log.h" #include "strv.h" #include "unit-name.h" +#include "conf-parser.h" +#include "load-fragment.h" + +static int load_dropin_config_file(Unit *u, const char *path) { + assert(u); + assert(path); + + if (!endswith(path, ".conf")) + return 0; + + return config_parse(path, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u); +} static int iterate_dir(Unit *u, const char *path, UnitDependency dependency) { - DIR *d; - struct dirent *de; + _cleanup_closedir_ DIR *d = NULL; int r; assert(u); @@ -38,37 +49,46 @@ static int iterate_dir(Unit *u, const char *path, UnitDependency dependency) { d = opendir(path); if (!d) { - if (errno == ENOENT) return 0; return -errno; } - while ((de = readdir(d))) { - char *f; + for (;;) { + struct dirent *de; + union dirent_storage buf; + _cleanup_free_ char *f = NULL; + int k; + + k = readdir_r(d, &buf.de, &de); + if (k != 0) { + log_error("Failed to read directory %s: %s", path, strerror(k)); + return -k; + } + + if (!de) + break; if (ignore_file(de->d_name)) continue; f = strjoin(path, "/", de->d_name, NULL); - if (!f) { - r = -ENOMEM; - goto finish; - } + if (!f) + return log_oom(); - r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true); - free(f); - - if (r < 0) - log_error("Cannot add dependency %s to %s, ignoring: %s", de->d_name, u->id, strerror(-r)); + if (dependency >= 0) { + r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true); + if (r < 0) + log_error("Cannot add dependency %s to %s, ignoring: %s", de->d_name, u->id, strerror(-r)); + } else { + r = load_dropin_config_file(u, f); + if (r < 0) + log_error("Cannot load drop-in configuration file %s for %s, ignoring: %s", f, u->id, strerror(-r)); + } } - r = 0; - -finish: - closedir(d); - return r; + return 0; } static int process_dir(Unit *u, const char *unit_path, const char *name, const char *suffix, UnitDependency dependency) { @@ -143,6 +163,11 @@ int unit_load_dropin(Unit *u) { r = process_dir(u, *p, t, ".requires", UNIT_REQUIRES); if (r < 0) return r; + + /* This loads the drop-in config snippets */ + r = process_dir(u, *p, t, ".d", _UNIT_TYPE_INVALID); + if (r < 0) + return r; } } diff --git a/src/core/unit.c b/src/core/unit.c index 45453dce64..f00cfedb89 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1781,6 +1781,7 @@ static const char *resolve_template(Unit *u, const char *name, const char*path, assert(u); assert(name || path); + assert(p); if (!name) name = path_get_file_name(path); @@ -1795,7 +1796,8 @@ static const char *resolve_template(Unit *u, const char *name, const char*path, else { char *i; - if (!(i = unit_name_to_prefix(u->id))) + i = unit_name_to_prefix(u->id); + if (!i) return NULL; s = unit_name_replace_instance(name, i); @@ -1812,22 +1814,20 @@ static const char *resolve_template(Unit *u, const char *name, const char*path, int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) { Unit *other; int r; - char *s; + _cleanup_free_ char *s = NULL; assert(u); assert(name || path); - if (!(name = resolve_template(u, name, path, &s))) + name = resolve_template(u, name, path, &s); + if (!name) return -ENOMEM; - if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0) - goto finish; - - r = unit_add_dependency(u, d, other, add_reference); + r = manager_load_unit(u->manager, name, path, NULL, &other); + if (r < 0) + return r; -finish: - free(s); - return r; + return unit_add_dependency(u, d, other, add_reference); } int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) { |