mirror of
https://github.com/systemd/systemd.git
synced 2025-03-28 02:50:16 +03:00
Merge pull request #8134 from keszybz/unit-load-paths
Various fixes to unit load paths, and systemd-analyze load-paths verb to list them
This commit is contained in:
commit
91761b1846
@ -91,6 +91,11 @@
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">dump</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">unit-paths</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
@ -188,6 +193,18 @@
|
||||
state. Its format is subject to change without notice and should
|
||||
not be parsed by applications.</para>
|
||||
|
||||
<para><command>systemd-analyze unit-paths</command> outputs a list of all
|
||||
directories from which unit files, <filename>.d</filename> overrides, and
|
||||
<filename>.wants</filename>, <filename>.requires</filename> symlinks may be
|
||||
loaded. Combine with <option>--user</option> to retrieve the list for the user
|
||||
manager instance, and <option>--global</option> for the global configuration of
|
||||
user manager instances. Note that this verb prints the list that is compiled into
|
||||
<command>systemd-analyze</command> itself, and does not comunicate with the
|
||||
running manager. Use
|
||||
<programlisting>systemctl [--user] [--global] show -p UnitPath --value</programlisting>
|
||||
to retrieve the actual list that the manager uses, with any empty directories
|
||||
omitted.</para>
|
||||
|
||||
<para><command>systemd-analyze log-level</command>
|
||||
prints the current log level of the <command>systemd</command> daemon.
|
||||
If an optional argument <replaceable>LEVEL</replaceable> is provided, then the command changes the current log
|
||||
@ -242,6 +259,13 @@
|
||||
<para>The following options are understood:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--system</option></term>
|
||||
|
||||
<listitem><para>Operates on the system systemd instance. This
|
||||
is the implied default.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--user</option></term>
|
||||
|
||||
@ -250,10 +274,10 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--system</option></term>
|
||||
<term><option>--global</option></term>
|
||||
|
||||
<listitem><para>Operates on the system systemd instance. This
|
||||
is the implied default.</para></listitem>
|
||||
<listitem><para>Operates on the system-wide configuration for
|
||||
user systemd instance.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -76,14 +76,33 @@
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para>Generators are small executables that live in <filename>&systemgeneratordir;/</filename> and other
|
||||
directories listed above.
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> will execute those
|
||||
binaries very early at bootup and at configuration reload time — before unit files are loaded. Generators may
|
||||
dynamically generate unit files (regular ones, instances as well as templates) and unit file
|
||||
<filename>.d/</filename> drop-ins, or create symbolic links to unit files to add additional dependencies or
|
||||
instantiate existing templates, thus extending or overriding existing definitions. Their main purpose is to convert
|
||||
configuration files that are not native unit files dynamically into native unit files.</para>
|
||||
<para>Generators are small executables that live in
|
||||
<filename>&systemgeneratordir;/</filename> and other directories listed above.
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
will execute those binaries very early at bootup and at configuration reload time
|
||||
— before unit files are loaded. Their main purpose is to convert configuration
|
||||
that is not native into dynamically generated unit files.</para>
|
||||
|
||||
<para>Each generator is called with three directory paths that are to be used for
|
||||
generator output. In these three directories, generators may dynamically generate
|
||||
unit files (regular ones, instances, as well as templates), unit file
|
||||
<filename>.d/</filename> drop-ins, and create symbolic links to unit files to add
|
||||
additional dependencies, create aliases, or instantiate existing templates. Those
|
||||
directories are included in the unit load path of
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
allowing generated configuration to extend or override existing
|
||||
definitions.</para>
|
||||
|
||||
<para>Directory paths for generator output differ by priority:
|
||||
<filename>…/generator.early</filename> has priority higher than the admin
|
||||
configuration in <filename>/etc</filename>, while
|
||||
<filename>…/generator</filename> has lower priority than
|
||||
<filename>/etc</filename> but higher than vendor configuration in
|
||||
<filename>/usr</filename>, and <filename>…/generator.late</filename> has priority
|
||||
lower than all other configuration. See the next section and the discussion of
|
||||
unit load paths and unit overriding in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<para>Generators are loaded from a set of paths determined during
|
||||
compilation, as listed above. System and user generators are loaded
|
||||
@ -110,171 +129,153 @@
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Writing generators</title>
|
||||
<title>Output directories</title>
|
||||
|
||||
<para>Generators are invoked with three arguments: paths to
|
||||
runtime directories where generators can place their generated
|
||||
unit files or symlinks.</para>
|
||||
<para>Generators are invoked with three arguments: paths to directories where
|
||||
generators can place their generated unit files or symlinks. By default those
|
||||
paths are runtime directories that are included in the search path of
|
||||
<command>systemd</command>, but a generator may be called with different paths
|
||||
for debugging purposes.</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para><parameter>normal-dir</parameter></para>
|
||||
<para>argv[1] may be used to override unit files in
|
||||
<filename>/usr</filename>, but not those in
|
||||
<filename>/run</filename> or in <filename>/etc</filename>.
|
||||
This means that unit files placed
|
||||
in this directory take precedence over vendor unit
|
||||
configuration but not over native user/administrator unit
|
||||
configuration.</para>
|
||||
<para>In normal use this is <filename>/run/systemd/generator</filename> in
|
||||
case of the system generators and
|
||||
<filename>$XDG_RUNTIME_DIR/generator</filename> in case of the user
|
||||
generators. Unit files placed in this directory take precedence over vendor
|
||||
unit configuration but not over native user/administrator unit configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><parameter>early-dir</parameter></para>
|
||||
<para>argv[2] may be used to override unit files in
|
||||
<filename>/usr</filename>, in <filename>/run</filename> and in
|
||||
<filename>/etc</filename>. This means that unit files placed
|
||||
in this directory take precedence over all configuration,
|
||||
both vendor and user/administrator.</para>
|
||||
<para>In normal use this is <filename>/run/systemd/generator.early</filename>
|
||||
in case of the system generators and
|
||||
<filename>$XDG_RUNTIME_DIR/generator.early</filename> in case of the user
|
||||
generators. Unit files placed in this directory override unit files in
|
||||
<filename>/usr</filename>, <filename>/run</filename> and
|
||||
<filename>/etc</filename>. This means that unit files placed in this
|
||||
directory take precedence over all normal configuration, both vendor and
|
||||
user/administrator.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><parameter>late-dir</parameter></para>
|
||||
<para>argv[3] may be used to extend the unit file tree without
|
||||
overriding any other unit files. Any native configuration
|
||||
files supplied by the vendor or user/administrator take
|
||||
precedence over the generated ones placed in this directory.
|
||||
</para>
|
||||
<para>In normal use this is <filename>/run/systemd/generator.late</filename>
|
||||
in case of the system generators and
|
||||
<filename>$XDG_RUNTIME_DIR/generator.late</filename> in case of the user
|
||||
generators. This directory may be used to extend the unit file tree without
|
||||
overriding any other unit files. Any native configuration files supplied by
|
||||
the vendor or user/administrator take precedence.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect2>
|
||||
<title>Notes</title>
|
||||
<refsect1>
|
||||
<title>Notes about writing generators</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
All generators are executed in parallel. That means all
|
||||
executables are started at the very same time and need to
|
||||
be able to cope with this parallelism.
|
||||
</para>
|
||||
</listitem>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>All generators are executed in parallel. That means all executables are
|
||||
started at the very same time and need to be able to cope with this
|
||||
parallelism.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Generators are run very early at boot and cannot rely on
|
||||
any external services. They may not talk to any other
|
||||
process. That includes simple things such as logging to
|
||||
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
or <command>systemd</command> itself (this means: no
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!
|
||||
Non-essential file systems like
|
||||
<filename>/var</filename> and <filename>/home</filename>
|
||||
are mounted after generators have run. Generators
|
||||
can however rely on the most basic kernel functionality to be
|
||||
available, including a mounted <filename>/sys</filename>,
|
||||
<filename>/proc</filename>, <filename>/dev</filename>,
|
||||
<filename>/usr</filename>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Generators are run very early at boot and cannot rely on any external
|
||||
services. They may not talk to any other process. That includes simple things
|
||||
such as logging to
|
||||
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
or <command>systemd</command> itself (this means: no
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!
|
||||
Non-essential file systems like <filename>/var</filename> and
|
||||
<filename>/home</filename> are mounted after generators have run. Generators
|
||||
can however rely on the most basic kernel functionality to be available,
|
||||
including a mounted <filename>/sys</filename>, <filename>/proc</filename>,
|
||||
<filename>/dev</filename>, <filename>/usr</filename>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Units written by generators are removed when the configuration
|
||||
is reloaded. That means the lifetime of the generated
|
||||
units is closely bound to the reload cycles of
|
||||
<command>systemd</command> itself.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Units written by generators are removed when the configuration is
|
||||
reloaded. That means the lifetime of the generated units is closely bound to
|
||||
the reload cycles of <command>systemd</command> itself.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Generators should only be used to generate unit files and symlinks to them, not any other kind of
|
||||
configuration. Due to the lifecycle logic mentioned above, generators are not a good fit to generate
|
||||
dynamic configuration for other services. If you need to generate dynamic configuration for other services,
|
||||
do so in normal services you order before the service in question.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Generators should only be used to generate unit files and symlinks to
|
||||
them, not any other kind of configuration. Due to the lifecycle logic
|
||||
mentioned above, generators are not a good fit to generate dynamic
|
||||
configuration for other services. If you need to generate dynamic
|
||||
configuration for other services, do so in normal services you order before
|
||||
the service in question.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Since
|
||||
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
is not available (see above), log messages have to be
|
||||
written to <filename>/dev/kmsg</filename> instead.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Since
|
||||
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
It is a good idea to use the
|
||||
<varname>SourcePath=</varname> directive in generated unit
|
||||
files to specify the source configuration file you are
|
||||
generating the unit from. This makes things more easily
|
||||
understood by the user and also has the benefit that
|
||||
systemd can warn the user about configuration files that
|
||||
changed on disk but have not been read yet by systemd.
|
||||
</para>
|
||||
</listitem>
|
||||
is not available (see above), log messages have to be written to
|
||||
<filename>/dev/kmsg</filename> instead.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Generators may write out dynamic unit files or just hook
|
||||
unit files into other units with the usual
|
||||
<filename>.wants/</filename> or
|
||||
<filename>.requires/</filename> symlinks. Often, it is
|
||||
nicer to simply instantiate a template unit file from
|
||||
<filename>/usr</filename> with a generator instead of
|
||||
writing out entirely dynamic unit files. Of course, this
|
||||
works only if a single parameter is to be used.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>It is a good idea to use the <varname>SourcePath=</varname> directive
|
||||
in generated unit files to specify the source configuration file you are
|
||||
generating the unit from. This makes things more easily understood by the
|
||||
user and also has the benefit that systemd can warn the user about
|
||||
configuration files that changed on disk but have not been read yet by
|
||||
systemd.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
If you are careful, you can implement generators in shell
|
||||
scripts. We do recommend C code however, since generators
|
||||
are executed synchronously and hence delay the
|
||||
entire boot if they are slow.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Generators may write out dynamic unit files or just hook unit files
|
||||
into other units with the usual <filename>.wants/</filename> or
|
||||
<filename>.requires/</filename> symlinks. Often, it is nicer to simply
|
||||
instantiate a template unit file from <filename>/usr</filename> with a
|
||||
generator instead of writing out entirely dynamic unit files. Of course, this
|
||||
works only if a single parameter is to be used.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Regarding overriding semantics: there are two rules we
|
||||
try to follow when thinking about the overriding semantics:
|
||||
</para>
|
||||
<listitem>
|
||||
<para>If you are careful, you can implement generators in shell scripts. We
|
||||
do recommend C code however, since generators are executed synchronously and
|
||||
hence delay the entire boot if they are slow.</para>
|
||||
</listitem>
|
||||
|
||||
<orderedlist numeration="lowerroman">
|
||||
<listitem>
|
||||
<para>User configuration should override vendor
|
||||
configuration. This (mostly) means that stuff from
|
||||
<filename>/etc</filename> should override stuff from
|
||||
<filename>/usr</filename>.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Regarding overriding semantics: there are two rules we try to follow
|
||||
when thinking about the overriding semantics:</para>
|
||||
|
||||
<listitem>
|
||||
<para>Native configuration should override non-native
|
||||
configuration. This (mostly) means that stuff you
|
||||
generate should never override native unit files for the
|
||||
same purpose.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<orderedlist numeration="lowerroman">
|
||||
<listitem>
|
||||
<para>User configuration should override vendor configuration. This
|
||||
(mostly) means that stuff from <filename>/etc</filename> should override
|
||||
stuff from <filename>/usr</filename>.</para>
|
||||
</listitem>
|
||||
|
||||
<para>Of these two rules the first rule is probably the more
|
||||
important one and breaks the second one sometimes. Hence,
|
||||
when deciding whether to use argv[1], argv[2], or argv[3],
|
||||
your default choice should probably be argv[1].</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Native configuration should override non-native configuration. This
|
||||
(mostly) means that stuff you generate should never override native unit
|
||||
files for the same purpose.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Instead of heading off now and writing all kind of
|
||||
generators for legacy configuration file formats, please
|
||||
think twice! It is often a better idea to just deprecate
|
||||
old stuff instead of keeping it artificially alive.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</refsect2>
|
||||
<para>Of these two rules the first rule is probably the more important one
|
||||
and breaks the second one sometimes. Hence, when deciding whether to use
|
||||
argv[1], argv[2], or argv[3], your default choice should probably be
|
||||
argv[1].</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Instead of heading off now and writing all kind of generators for
|
||||
legacy configuration file formats, please think twice! It is often a better
|
||||
idea to just deprecate old stuff instead of keeping it artificially alive.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -283,22 +284,18 @@
|
||||
<title>systemd-fstab-generator</title>
|
||||
|
||||
<para><citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
converts <filename>/etc/fstab</filename> into native mount
|
||||
units. It uses argv[1] as location to place the generated unit
|
||||
files in order to allow the user to override
|
||||
<filename>/etc/fstab</filename> with her own native unit files,
|
||||
but also to ensure that <filename>/etc/fstab</filename>
|
||||
overrides any vendor default from <filename>/usr</filename>.
|
||||
</para>
|
||||
converts <filename>/etc/fstab</filename> into native mount units. It uses
|
||||
argv[1] as location to place the generated unit files in order to allow the
|
||||
user to override <filename>/etc/fstab</filename> with her own native unit
|
||||
files, but also to ensure that <filename>/etc/fstab</filename> overrides any
|
||||
vendor default from <filename>/usr</filename>.</para>
|
||||
|
||||
<para>After editing <filename>/etc/fstab</filename>, the user
|
||||
should invoke <command>systemctl daemon-reload</command>. This
|
||||
will re-run all generators and cause <command>systemd</command>
|
||||
to reload units from disk. To actually mount new directories
|
||||
added to <filename>fstab</filename>, <command>systemctl start
|
||||
<replaceable>/path/to/mountpoint</replaceable></command> or
|
||||
<command>systemctl start local-fs.target</command> may be used.
|
||||
</para>
|
||||
<para>After editing <filename>/etc/fstab</filename>, the user should invoke
|
||||
<command>systemctl daemon-reload</command>. This will re-run all generators and
|
||||
cause <command>systemd</command> to reload units from disk. To actually mount
|
||||
new directories added to <filename>fstab</filename>, <command>systemctl start
|
||||
<replaceable>/path/to/mountpoint</replaceable></command> or <command>systemctl
|
||||
start local-fs.target</command> may be used.</para>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
@ -307,9 +304,9 @@
|
||||
<para><citerefentry><refentrytitle>systemd-system-update-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
temporarily redirects <filename>default.target</filename> to
|
||||
<filename>system-update.target</filename>, if a system update is
|
||||
scheduled. Since this needs to override the default user
|
||||
configuration for <filename>default.target</filename>, it uses
|
||||
argv[2]. For details about this logic, see
|
||||
scheduled. Since this needs to override the default user configuration for
|
||||
<filename>default.target</filename>, it uses argv[2]. For details about this
|
||||
logic, see
|
||||
<citerefentry><refentrytitle>systemd.offline-updates</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
</para>
|
||||
</example>
|
||||
|
@ -65,19 +65,31 @@
|
||||
<filename><replaceable>slice</replaceable>.slice</filename>,
|
||||
<filename><replaceable>scope</replaceable>.scope</filename></para>
|
||||
|
||||
<para><literallayout><filename>/etc/systemd/system/*</filename>
|
||||
<para><literallayout><filename>/etc/systemd/system.control/*</filename>
|
||||
<filename>/run/systemd/system.control/*</filename>
|
||||
<filename>/run/systemd/transient/*</filename>
|
||||
<filename>/run/systemd/generator.early/*</filename>
|
||||
<filename>/etc/systemd/system/*</filename>
|
||||
<filename>/run/systemd/system/*</filename>
|
||||
<filename>/usr/lib/systemd/system/*</filename>
|
||||
<filename>/run/systemd/generator/*</filename>
|
||||
<filename>…</filename>
|
||||
<filename>/usr/lib/systemd/system/*</filename>
|
||||
<filename>/run/systemd/generator.late/*</filename>
|
||||
</literallayout></para>
|
||||
|
||||
<para><literallayout><filename>~/.config/systemd/user/*</filename>
|
||||
<para><literallayout><filename>~/.config/systemd/user.control/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/user.control/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/transient/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/generator.early/*</filename>
|
||||
<filename>~/.config/systemd/user/*</filename>
|
||||
<filename>/etc/systemd/user/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/user/*</filename>
|
||||
<filename>/run/systemd/user/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/generator/*</filename>
|
||||
<filename>~/.local/share/systemd/user/*</filename>
|
||||
<filename>/usr/lib/systemd/user/*</filename>
|
||||
<filename>…</filename>
|
||||
<filename>/usr/lib/systemd/user/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/generator.late/*</filename>
|
||||
</literallayout></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -342,6 +354,22 @@
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><filename>/etc/systemd/system.control</filename></entry>
|
||||
<entry morerows="1">Persistent and transient configuration created using the dbus API</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/system.control</filename></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/transient</filename></entry>
|
||||
<entry>Dynamic configuration for transient units</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/generator.early</filename></entry>
|
||||
<entry>Generated units with high priority (see <replaceable>early-dir</replaceable> in <citerefentry
|
||||
><refentrytitle>system.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/etc/systemd/system</filename></entry>
|
||||
<entry>Local configuration</entry>
|
||||
@ -350,9 +378,22 @@
|
||||
<entry><filename>/run/systemd/system</filename></entry>
|
||||
<entry>Runtime units</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/generator</filename></entry>
|
||||
<entry>Generated units with medium priority (see <replaceable>normal-dir</replaceable> in <citerefentry
|
||||
><refentrytitle>system.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/usr/local/lib/systemd/system</filename></entry>
|
||||
<entry morerows="1">Units of installed packages</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/usr/lib/systemd/system</filename></entry>
|
||||
<entry>Units of installed packages</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/generator.late</filename></entry>
|
||||
<entry>Generated units with low priority (see <replaceable>late-dir</replaceable> in <citerefentry
|
||||
><refentrytitle>system.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@ -374,12 +415,25 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><filename>$XDG_CONFIG_HOME/systemd/user</filename></entry>
|
||||
<entry>User configuration (only used when $XDG_CONFIG_HOME is set)</entry>
|
||||
<entry><filename>$XDG_CONFIG_HOME/systemd/user.control</filename> or <filename
|
||||
>~/.config/systemd/user.control</filename></entry>
|
||||
<entry morerows="1">Persistent and transient configuration created using the dbus API (<varname>$XDG_CONFIG_HOME</varname> is used if set, <filename>~/.config</filename> otherwise)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>$HOME/.config/systemd/user</filename></entry>
|
||||
<entry>User configuration (only used when $XDG_CONFIG_HOME is not set)</entry>
|
||||
<entry><filename>$XDG_RUNTIME_DIR/systemd/user.control</filename></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/transient</filename></entry>
|
||||
<entry>Dynamic configuration for transient units</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/run/systemd/generator.early</filename></entry>
|
||||
<entry>Generated units with high priority (see <replaceable>early-dir</replaceable> in <citerefentry
|
||||
><refentrytitle>system.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>$XDG_CONFIG_HOME/systemd/user</filename> or <filename>$HOME/.config/systemd/user</filename></entry>
|
||||
<entry>User configuration (<varname>$XDG_CONFIG_HOME</varname> is used if set, <filename>~/.config</filename> otherwise)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/etc/systemd/user</filename></entry>
|
||||
@ -394,27 +448,50 @@
|
||||
<entry>Runtime units</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>$XDG_DATA_HOME/systemd/user</filename></entry>
|
||||
<entry>Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is set)</entry>
|
||||
<entry><filename>$XDG_RUNTIME_DIR/systemd/generator</filename></entry>
|
||||
<entry>Generated units with medium priority (see <replaceable>normal-dir</replaceable> in <citerefentry
|
||||
><refentrytitle>system.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>$HOME/.local/share/systemd/user</filename></entry>
|
||||
<entry>Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is not set)</entry>
|
||||
<entry><filename>$XDG_DATA_HOME/systemd/user</filename> or <filename>$HOME/.local/share/systemd/user</filename></entry>
|
||||
<entry>Units of packages that have been installed in the home directory (<varname>$XDG_DATA_HOME</varname> is used if set, <filename>~/.local/share</filename> otherwise)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>$dir/systemd/user</filename> for each <varname noindex='true'>$dir</varname> in <varname>$XDG_DATA_DIRS</varname></entry>
|
||||
<entry>Additional locations for installed user units, one for each entry in <varname>$XDG_DATA_DIRS</varname></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/usr/local/lib/systemd/user</filename></entry>
|
||||
<entry morerows="1">Units of packages that have been installed system-wide</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>/usr/lib/systemd/user</filename></entry>
|
||||
<entry>Units of packages that have been installed system-wide</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><filename>$XDG_RUNTIME_DIR/systemd/generator.late</filename></entry>
|
||||
<entry>Generated units with low priority (see <replaceable>late-dir</replaceable> in <citerefentry
|
||||
><refentrytitle>system.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>Additional units might be loaded into systemd ("linked")
|
||||
from directories not on the unit load path. See the
|
||||
<command>link</command> command for
|
||||
<para>The set of load paths for the user manager instance may be augmented or
|
||||
changed using various environment variables. And environment variables may in
|
||||
turn be set using environment generators, see
|
||||
<citerefentry><refentrytitle>system.environment-generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
In particular, <varname>$XDG_DATA_HOME</varname> and
|
||||
<varname>$XDG_DATA_DIRS</varname> may be easily set using
|
||||
<citerefentry><refentrytitle>systemd-environment-d-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
Thus, directories listed here are just the defaults. To see the actual list that
|
||||
would be used based on compilation options and current environment use
|
||||
<programlisting>systemd-analyze --user unit-paths</programlisting>
|
||||
</para>
|
||||
|
||||
<para>Moreover, additional units might be loaded into systemd ("linked") from
|
||||
directories not on the unit load path. See the <command>link</command> command
|
||||
for
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
|
||||
Also, some units are dynamically created via a
|
||||
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
@ -36,13 +36,13 @@ _systemd_analyze() {
|
||||
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
local -A OPTS=(
|
||||
[STANDALONE]='-h --help --version --system --user --order --require --no-pager
|
||||
[STANDALONE]='-h --help --version --system --user --global --order --require --no-pager
|
||||
--man=no --generators=yes'
|
||||
[ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern'
|
||||
)
|
||||
|
||||
local -A VERBS=(
|
||||
[STANDALONE]='time blame plot dump calendar'
|
||||
[STANDALONE]='time blame plot dump unit-paths calendar'
|
||||
[CRITICAL_CHAIN]='critical-chain'
|
||||
[DOT]='dot'
|
||||
[LOG_LEVEL]='log-level'
|
||||
@ -85,7 +85,7 @@ _systemd_analyze() {
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[STANDALONE]}; then
|
||||
if [[ $cur = -* ]]; then
|
||||
comps='--help --version --system --user'
|
||||
comps='--help --version --system --user --global'
|
||||
fi
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[CRITICAL_CHAIN]}; then
|
||||
@ -95,7 +95,7 @@ _systemd_analyze() {
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[DOT]}; then
|
||||
if [[ $cur = -* ]]; then
|
||||
comps='--help --version --system --user --from-pattern --to-pattern --order --require'
|
||||
comps='--help --version --system --user --global --from-pattern --to-pattern --order --require'
|
||||
fi
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then
|
||||
@ -119,7 +119,7 @@ _systemd_analyze() {
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[VERIFY]}; then
|
||||
if [[ $cur = -* ]]; then
|
||||
comps='--help --version --system --user --man=no --generators=yes'
|
||||
comps='--help --version --system --user --global --man=no --generators=yes'
|
||||
else
|
||||
comps=$( compgen -A file -- "$cur" )
|
||||
compopt -o filenames
|
||||
|
@ -33,6 +33,7 @@ _systemd_analyze_command(){
|
||||
'plot:Output SVG graphic showing service initialization'
|
||||
'dot:Dump dependency graph (in dot(1) format)'
|
||||
'dump:Dump server status'
|
||||
'unit-paths':List unit load paths'
|
||||
'log-level:Get/set systemd log threshold'
|
||||
'log-target:Get/set systemd log target'
|
||||
'service-watchdogs:Get/set service watchdog status'
|
||||
@ -62,6 +63,7 @@ _arguments \
|
||||
'--version[Show package version]' \
|
||||
'--system[Operate on system systemd instance]' \
|
||||
'--user[Operate on user systemd instance]' \
|
||||
'--global[Show global user instance config]' \
|
||||
'--no-pager[Do not pipe output into a pager]' \
|
||||
'--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \
|
||||
'--order[When generating graph for dot, show only order]' \
|
||||
|
@ -80,7 +80,7 @@ static usec_t arg_fuzz = 0;
|
||||
static bool arg_no_pager = false;
|
||||
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
||||
static const char *arg_host = NULL;
|
||||
static bool arg_user = false;
|
||||
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
|
||||
static bool arg_man = true;
|
||||
static bool arg_generators = false;
|
||||
|
||||
@ -132,10 +132,12 @@ struct host_info {
|
||||
};
|
||||
|
||||
static int acquire_bus(bool need_full_bus, sd_bus **bus) {
|
||||
bool user = arg_scope != UNIT_FILE_SYSTEM;
|
||||
|
||||
if (need_full_bus)
|
||||
return bus_connect_transport(arg_transport, arg_host, arg_user, bus);
|
||||
return bus_connect_transport(arg_transport, arg_host, user, bus);
|
||||
else
|
||||
return bus_connect_transport_systemd(arg_transport, arg_host, arg_user, bus);
|
||||
return bus_connect_transport_systemd(arg_transport, arg_host, user, bus);
|
||||
}
|
||||
|
||||
static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
|
||||
@ -294,7 +296,12 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
if (arg_user) {
|
||||
if (arg_scope == UNIT_FILE_SYSTEM) {
|
||||
if (times.initrd_time > 0)
|
||||
times.kernel_done_time = times.initrd_time;
|
||||
else
|
||||
times.kernel_done_time = times.userspace_time;
|
||||
} else {
|
||||
/*
|
||||
* User-instance-specific timestamps processing
|
||||
* (see comment to reverse_offset in struct boot_times).
|
||||
@ -312,11 +319,6 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
|
||||
|
||||
subtract_timestamp(×.unitsload_start_time, times.reverse_offset);
|
||||
subtract_timestamp(×.unitsload_finish_time, times.reverse_offset);
|
||||
} else {
|
||||
if (times.initrd_time)
|
||||
times.kernel_done_time = times.initrd_time;
|
||||
else
|
||||
times.kernel_done_time = times.userspace_time;
|
||||
}
|
||||
|
||||
cached = true;
|
||||
@ -439,8 +441,7 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
return c;
|
||||
|
||||
fail:
|
||||
if (unit_times)
|
||||
free_unit_times(unit_times, (unsigned) c);
|
||||
free_unit_times(unit_times, (unsigned) c);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -537,11 +538,11 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
|
||||
size = sizeof(buf);
|
||||
|
||||
size = strpcpyf(&ptr, size, "Startup finished in ");
|
||||
if (t->firmware_time)
|
||||
if (t->firmware_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC));
|
||||
if (t->loader_time)
|
||||
if (t->loader_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), t->loader_time, USEC_PER_MSEC));
|
||||
if (t->kernel_time)
|
||||
if (t->kernel_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time, USEC_PER_MSEC));
|
||||
if (t->initrd_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC));
|
||||
@ -550,7 +551,7 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
|
||||
if (t->kernel_time > 0)
|
||||
strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
|
||||
|
||||
if (unit_id && (activated_time > 0 && activated_time != USEC_INFINITY))
|
||||
if (unit_id && activated_time > 0 && activated_time != USEC_INFINITY)
|
||||
size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id, format_timespan(ts, sizeof(ts), activated_time - t->userspace_time, USEC_PER_MSEC));
|
||||
else if (unit_id && activated_time == 0)
|
||||
size = strpcpyf(&ptr, size, "\n%s was never reached", unit_id);
|
||||
@ -629,14 +630,14 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
|
||||
if (boot->firmware_time > boot->loader_time)
|
||||
m++;
|
||||
if (boot->loader_time) {
|
||||
if (boot->loader_time > 0) {
|
||||
m++;
|
||||
if (width < 1000.0)
|
||||
width = 1000.0;
|
||||
}
|
||||
if (boot->initrd_time)
|
||||
if (boot->initrd_time > 0)
|
||||
m++;
|
||||
if (boot->kernel_time)
|
||||
if (boot->kernel_time > 0)
|
||||
m++;
|
||||
|
||||
for (u = times; u < times + n; u++) {
|
||||
@ -725,22 +726,22 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
|
||||
svg_graph_box(m, -(double) boot->firmware_time, boot->finish_time);
|
||||
|
||||
if (boot->firmware_time) {
|
||||
if (boot->firmware_time > 0) {
|
||||
svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y);
|
||||
svg_text(true, -(double) boot->firmware_time, y, "firmware");
|
||||
y++;
|
||||
}
|
||||
if (boot->loader_time) {
|
||||
if (boot->loader_time > 0) {
|
||||
svg_bar("loader", -(double) boot->loader_time, 0, y);
|
||||
svg_text(true, -(double) boot->loader_time, y, "loader");
|
||||
y++;
|
||||
}
|
||||
if (boot->kernel_time) {
|
||||
if (boot->kernel_time > 0) {
|
||||
svg_bar("kernel", 0, boot->kernel_done_time, y);
|
||||
svg_text(true, 0, y, "kernel");
|
||||
y++;
|
||||
}
|
||||
if (boot->initrd_time) {
|
||||
if (boot->initrd_time > 0) {
|
||||
svg_bar("initrd", boot->initrd_time, boot->userspace_time, y);
|
||||
svg_text(true, boot->initrd_time, y, "initrd");
|
||||
y++;
|
||||
@ -818,7 +819,7 @@ static int list_dependencies_print(const char *name, unsigned int level, unsigne
|
||||
printf("%s", special_glyph(last ? TREE_RIGHT : TREE_BRANCH));
|
||||
|
||||
if (times) {
|
||||
if (times->time)
|
||||
if (times->time > 0)
|
||||
printf("%s%s @%s +%s%s", ansi_highlight_red(), name,
|
||||
format_timespan(ts, sizeof(ts), times->activating - boot->userspace_time, USEC_PER_MSEC),
|
||||
format_timespan(ts2, sizeof(ts2), times->time, USEC_PER_MSEC), ansi_normal());
|
||||
@ -864,6 +865,11 @@ static int list_dependencies_compare(const void *_a, const void *_b) {
|
||||
return usb - usa;
|
||||
}
|
||||
|
||||
static bool times_in_range(const struct unit_times *times, const struct boot_times *boot) {
|
||||
return times &&
|
||||
times->activated > 0 && times->activated <= boot->finish_time;
|
||||
}
|
||||
|
||||
static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int level, char ***units,
|
||||
unsigned int branches) {
|
||||
_cleanup_strv_free_ char **deps = NULL;
|
||||
@ -889,11 +895,9 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev
|
||||
|
||||
STRV_FOREACH(c, deps) {
|
||||
times = hashmap_get(unit_times_hashmap, *c);
|
||||
if (times
|
||||
&& times->activated
|
||||
&& times->activated <= boot->finish_time
|
||||
&& (times->activated >= service_longest
|
||||
|| service_longest == 0)) {
|
||||
if (times_in_range(times, boot) &&
|
||||
(times->activated >= service_longest
|
||||
|| service_longest == 0)) {
|
||||
service_longest = times->activated;
|
||||
break;
|
||||
}
|
||||
@ -904,7 +908,8 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev
|
||||
|
||||
STRV_FOREACH(c, deps) {
|
||||
times = hashmap_get(unit_times_hashmap, *c);
|
||||
if (times && times->activated && times->activated <= boot->finish_time && (service_longest - times->activated) <= arg_fuzz)
|
||||
if (times_in_range(times, boot) &&
|
||||
service_longest - times->activated <= arg_fuzz)
|
||||
to_print++;
|
||||
}
|
||||
|
||||
@ -913,10 +918,8 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev
|
||||
|
||||
STRV_FOREACH(c, deps) {
|
||||
times = hashmap_get(unit_times_hashmap, *c);
|
||||
if (!times
|
||||
|| !times->activated
|
||||
|| times->activated > boot->finish_time
|
||||
|| service_longest - times->activated > arg_fuzz)
|
||||
if (!times_in_range(times, boot) ||
|
||||
service_longest - times->activated > arg_fuzz)
|
||||
continue;
|
||||
|
||||
to_print--;
|
||||
@ -938,7 +941,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!to_print)
|
||||
if (to_print == 0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@ -1414,6 +1417,21 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) {
|
||||
return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata);
|
||||
}
|
||||
|
||||
static int dump_unit_paths(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_lookup_paths_free_ LookupPaths paths = {};
|
||||
int r;
|
||||
char **p;
|
||||
|
||||
r = lookup_paths_init(&paths, arg_scope, 0, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "lookup_paths_init() failed: %m");
|
||||
|
||||
STRV_FOREACH(p, paths.search_path)
|
||||
puts(*p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
static void dump_syscall_filter(const SyscallFilterSet *set) {
|
||||
const char *syscall;
|
||||
@ -1584,10 +1602,7 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
static int do_verify(int argc, char *argv[], void *userdata) {
|
||||
return verify_units(strv_skip(argv, 1),
|
||||
arg_user ? UNIT_FILE_USER : UNIT_FILE_SYSTEM,
|
||||
arg_man,
|
||||
arg_generators);
|
||||
return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators);
|
||||
}
|
||||
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
@ -1601,6 +1616,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --system Operate on system systemd instance\n"
|
||||
" --user Operate on user systemd instance\n"
|
||||
" --global Operate on global user configuration\n"
|
||||
" -H --host=[USER@]HOST Operate on remote host\n"
|
||||
" -M --machine=CONTAINER Operate on local container\n"
|
||||
" --order Show only order in the graph\n"
|
||||
@ -1620,6 +1636,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" log-level [LEVEL] Get/set logging threshold for manager\n"
|
||||
" log-target [TARGET] Get/set logging target for manager\n"
|
||||
" dump Output state serialization of service manager\n"
|
||||
" unit-paths List load directories for units\n"
|
||||
" syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
|
||||
" verify FILE... Check unit files for correctness\n"
|
||||
" calendar SPEC... Validate repetitive calendar time events\n"
|
||||
@ -1638,8 +1655,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_ORDER,
|
||||
ARG_REQUIRE,
|
||||
ARG_USER,
|
||||
ARG_SYSTEM,
|
||||
ARG_USER,
|
||||
ARG_GLOBAL,
|
||||
ARG_DOT_FROM_PATTERN,
|
||||
ARG_DOT_TO_PATTERN,
|
||||
ARG_FUZZ,
|
||||
@ -1653,8 +1671,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "order", no_argument, NULL, ARG_ORDER },
|
||||
{ "require", no_argument, NULL, ARG_REQUIRE },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "global", no_argument, NULL, ARG_GLOBAL },
|
||||
{ "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN },
|
||||
{ "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN },
|
||||
{ "fuzz", required_argument, NULL, ARG_FUZZ },
|
||||
@ -1680,12 +1699,16 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_USER:
|
||||
arg_user = true;
|
||||
case ARG_SYSTEM:
|
||||
arg_scope = UNIT_FILE_SYSTEM;
|
||||
break;
|
||||
|
||||
case ARG_SYSTEM:
|
||||
arg_user = false;
|
||||
case ARG_USER:
|
||||
arg_scope = UNIT_FILE_USER;
|
||||
break;
|
||||
|
||||
case ARG_GLOBAL:
|
||||
arg_scope = UNIT_FILE_GLOBAL;
|
||||
break;
|
||||
|
||||
case ARG_ORDER:
|
||||
@ -1763,6 +1786,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option code.");
|
||||
}
|
||||
|
||||
if (arg_scope == UNIT_FILE_GLOBAL &&
|
||||
!STR_IN_SET(argv[optind] ?: "time", "dot", "unit-paths", "verify")) {
|
||||
log_error("Option --global only makes sense with verbs dot, unit-paths, verify.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 1; /* work to do */
|
||||
}
|
||||
|
||||
@ -1783,6 +1812,7 @@ int main(int argc, char *argv[]) {
|
||||
{ "set-log-target", 2, 2, 0, set_log_target },
|
||||
{ "get-log-target", VERB_ANY, 1, 0, get_log_target },
|
||||
{ "dump", VERB_ANY, 1, 0, dump },
|
||||
{ "unit-paths", 1, 1, 0, dump_unit_paths },
|
||||
{ "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters },
|
||||
{ "verify", 2, VERB_ANY, 0, do_verify },
|
||||
{ "calendar", 2, VERB_ANY, 0, test_calendar },
|
||||
|
@ -1260,9 +1260,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
|
||||
if (!lease->have_subnet_mask) {
|
||||
r = dhcp_lease_set_default_subnet_mask(lease);
|
||||
if (r < 0) {
|
||||
log_dhcp_client(client, "received lease lacks subnet "
|
||||
"mask, and a fallback one can not be "
|
||||
"generated, ignoring");
|
||||
log_dhcp_client(client,
|
||||
"received lease lacks subnet mask, "
|
||||
"and a fallback one cannot be generated, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
}
|
||||
@ -1331,9 +1331,9 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le
|
||||
if (lease->subnet_mask == INADDR_ANY) {
|
||||
r = dhcp_lease_set_default_subnet_mask(lease);
|
||||
if (r < 0) {
|
||||
log_dhcp_client(client, "received lease lacks subnet "
|
||||
"mask, and a fallback one can not be "
|
||||
"generated, ignoring");
|
||||
log_dhcp_client(client,
|
||||
"received lease lacks subnet mask, "
|
||||
"and a fallback one cannot be generated, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ _public_ const char *udev_device_get_driver(struct udev_device *udev_device)
|
||||
*
|
||||
* Retrieve the devtype string of the udev device.
|
||||
*
|
||||
* Returns: the devtype name of the udev device, or #NULL if it can not be determined
|
||||
* Returns: the devtype name of the udev device, or #NULL if it cannot be determined
|
||||
**/
|
||||
_public_ const char *udev_device_get_devtype(struct udev_device *udev_device)
|
||||
{
|
||||
@ -168,7 +168,7 @@ _public_ const char *udev_device_get_devtype(struct udev_device *udev_device)
|
||||
* Retrieve the subsystem string of the udev device. The string does not
|
||||
* contain any "/".
|
||||
*
|
||||
* Returns: the subsystem name of the udev device, or #NULL if it can not be determined
|
||||
* Returns: the subsystem name of the udev device, or #NULL if it cannot be determined
|
||||
**/
|
||||
_public_ const char *udev_device_get_subsystem(struct udev_device *udev_device)
|
||||
{
|
||||
|
@ -200,14 +200,14 @@ int config_parse_vxlan_address(const char *unit,
|
||||
|
||||
if (streq(lvalue, "Group")) {
|
||||
if (r <= 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan %s invalid multicast address, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
v->remote_family = f;
|
||||
} else {
|
||||
if (r > 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan %s can not be multicast address, ignoring assignment: %s", lvalue, rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -776,7 +776,7 @@ int config_parse_address(const char *unit,
|
||||
if (!e && f == AF_INET) {
|
||||
r = in4_addr_default_prefixlen(&buffer.in, &n->prefixlen);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address);
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length not specified, and a default one cannot be deduced for '%s', ignoring assignment", address);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ int config_parse_ipv6_proxy_ndp_address(
|
||||
r = in_addr_is_null(AF_INET6, &buffer);
|
||||
if (r != 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"IPv6 proxy NDP address can not be the ANY address, ignoring: %s", rvalue);
|
||||
"IPv6 proxy NDP address cannot be the ANY address, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -635,13 +635,13 @@ int config_parse_netdev(const char *unit,
|
||||
case NETDEV_KIND_VCAN:
|
||||
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Can not add NetDev '%s' to network: %m", rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add NetDev '%s' to network: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
assert_not_reached("Can not parse NetDev");
|
||||
assert_not_reached("Cannot parse NetDev");
|
||||
}
|
||||
|
||||
netdev_ref(netdev);
|
||||
@ -894,12 +894,12 @@ int config_parse_ipv6token(
|
||||
|
||||
r = in_addr_is_null(AF_INET6, &buffer);
|
||||
if (r != 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,8 @@ int xdg_user_dirs(char ***ret_config_dirs, char ***ret_data_dirs) {
|
||||
static char** user_dirs(
|
||||
const char *persistent_config,
|
||||
const char *runtime_config,
|
||||
const char *global_persistent_config,
|
||||
const char *global_runtime_config,
|
||||
const char *generator,
|
||||
const char *generator_early,
|
||||
const char *generator_late,
|
||||
@ -209,12 +211,19 @@ static char** user_dirs(
|
||||
if (strv_extend(&res, persistent_config) < 0)
|
||||
return NULL;
|
||||
|
||||
/* global config has lower priority than the user config of the same type */
|
||||
if (strv_extend(&res, global_persistent_config) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strv_extend_strv(&res, (char**) user_config_unit_paths, false) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strv_extend(&res, runtime_config) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strv_extend(&res, global_runtime_config) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strv_extend(&res, generator) < 0)
|
||||
return NULL;
|
||||
|
||||
@ -411,11 +420,11 @@ static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **r
|
||||
}
|
||||
|
||||
case UNIT_FILE_USER:
|
||||
r = xdg_user_config_dir(&a, "/systemd/system.control");
|
||||
r = xdg_user_config_dir(&a, "/systemd/user.control");
|
||||
if (r < 0 && r != -ENXIO)
|
||||
return r;
|
||||
|
||||
r = xdg_user_runtime_dir(runtime, "/systemd/system.control");
|
||||
r = xdg_user_runtime_dir(runtime, "/systemd/user.control");
|
||||
if (r < 0) {
|
||||
if (r != -ENXIO)
|
||||
return r;
|
||||
@ -484,6 +493,7 @@ int lookup_paths_init(
|
||||
_cleanup_free_ char
|
||||
*root = NULL,
|
||||
*persistent_config = NULL, *runtime_config = NULL,
|
||||
*global_persistent_config = NULL, *global_runtime_config = NULL,
|
||||
*generator = NULL, *generator_early = NULL, *generator_late = NULL,
|
||||
*transient = NULL,
|
||||
*persistent_control = NULL, *runtime_control = NULL;
|
||||
@ -522,6 +532,12 @@ int lookup_paths_init(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (scope == UNIT_FILE_USER) {
|
||||
r = acquire_config_dirs(UNIT_FILE_GLOBAL, &global_persistent_config, &global_runtime_config);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) {
|
||||
/* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
|
||||
r = acquire_generator_dirs(scope, tempdir,
|
||||
@ -610,20 +626,21 @@ int lookup_paths_init(
|
||||
runtime_config,
|
||||
"/run/systemd/user",
|
||||
STRV_IFNOTNULL(generator),
|
||||
"/usr/local/lib/systemd/user",
|
||||
"/usr/local/share/systemd/user",
|
||||
"/usr/share/systemd/user",
|
||||
"/usr/local/lib/systemd/user",
|
||||
USER_DATA_UNIT_PATH,
|
||||
"/usr/lib/systemd/user",
|
||||
"/usr/share/systemd/user",
|
||||
STRV_IFNOTNULL(generator_late),
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case UNIT_FILE_USER:
|
||||
add = user_dirs(persistent_config, runtime_config,
|
||||
global_persistent_config, global_runtime_config,
|
||||
generator, generator_early, generator_late,
|
||||
transient,
|
||||
persistent_config, runtime_control);
|
||||
persistent_control, runtime_control);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -52,6 +52,36 @@ static void test_paths(UnitFileScope scope) {
|
||||
assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
|
||||
}
|
||||
|
||||
static void test_user_and_global_paths(void) {
|
||||
_cleanup_lookup_paths_free_ LookupPaths lp_global = {}, lp_user = {};
|
||||
char **u, **g, **p;
|
||||
unsigned k = 0;
|
||||
|
||||
assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0);
|
||||
|
||||
assert_se(lookup_paths_init(&lp_global, UNIT_FILE_GLOBAL, 0, NULL) == 0);
|
||||
assert_se(lookup_paths_init(&lp_user, UNIT_FILE_USER, 0, NULL) == 0);
|
||||
g = lp_global.search_path;
|
||||
u = lp_user.search_path;
|
||||
|
||||
/* Go over all entries in global search path, and verify
|
||||
* that they also exist in the user search path. Skip any
|
||||
* entries in user search path which don't exist in the global
|
||||
* one, but not vice versa. */
|
||||
log_info("/* %s */", __func__);
|
||||
STRV_FOREACH(p, g) {
|
||||
while (u[k] && !streq(*p, u[k])) {
|
||||
log_info("+ %s", u[k]);
|
||||
k++;
|
||||
}
|
||||
log_info(" %s", *p);
|
||||
assert(u[k]); /* If NULL, we didn't find a matching entry */
|
||||
k++;
|
||||
}
|
||||
STRV_FOREACH(p, u + k)
|
||||
log_info("+ %s", *p);
|
||||
}
|
||||
|
||||
static void print_generator_binary_paths(UnitFileScope scope) {
|
||||
_cleanup_strv_free_ char **paths;
|
||||
char **dir;
|
||||
@ -72,6 +102,8 @@ int main(int argc, char **argv) {
|
||||
test_paths(UNIT_FILE_USER);
|
||||
test_paths(UNIT_FILE_GLOBAL);
|
||||
|
||||
test_user_and_global_paths();
|
||||
|
||||
print_generator_binary_paths(UNIT_FILE_SYSTEM);
|
||||
print_generator_binary_paths(UNIT_FILE_USER);
|
||||
|
||||
|
@ -136,7 +136,7 @@ static void print_status_info(const StatusInfo *i) {
|
||||
if (i->rtc_local)
|
||||
printf("\n%s"
|
||||
"Warning: The system is configured to read the RTC time in the local time zone.\n"
|
||||
" This mode can not be fully supported. It will create various problems\n"
|
||||
" This mode cannot be fully supported. It will create various problems\n"
|
||||
" with time zone changes and daylight saving time adjustments. The RTC\n"
|
||||
" time is never updated, it relies on external facilities to maintain it.\n"
|
||||
" If at all possible, use RTC in UTC by calling\n"
|
||||
|
@ -147,7 +147,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
if (clock_is_localtime(NULL) > 0) {
|
||||
log_info("The system is configured to read the RTC time in the local time zone. "
|
||||
"This mode can not be fully supported. All system time to RTC updates are disabled.");
|
||||
"This mode cannot be fully supported. All system time to RTC updates are disabled.");
|
||||
m->rtc_local_time = true;
|
||||
}
|
||||
|
||||
|
@ -566,7 +566,7 @@ static int cd_profiles(struct udev *udev, int fd)
|
||||
log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len);
|
||||
|
||||
if (len > sizeof(features)) {
|
||||
log_debug("can not get features in a single query, truncating");
|
||||
log_debug("cannot get features in a single query, truncating");
|
||||
len = sizeof(features);
|
||||
} else if (len <= 8)
|
||||
len = sizeof(features);
|
||||
@ -588,7 +588,7 @@ static int cd_profiles(struct udev *udev, int fd)
|
||||
log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len);
|
||||
|
||||
if (len > sizeof(features)) {
|
||||
log_debug("can not get features in a single query, truncating");
|
||||
log_debug("cannot get features in a single query, truncating");
|
||||
len = sizeof(features);
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply,
|
||||
mode |= S_IFCHR;
|
||||
|
||||
if (lstat(devnode, &stats) != 0) {
|
||||
err = log_debug_errno(errno, "can not stat() node '%s' (%m)", devnode);
|
||||
err = log_debug_errno(errno, "cannot stat() node '%s' (%m)", devnode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -648,7 +648,7 @@ static bool is_devpath_busy(Manager *manager, struct event *event) {
|
||||
|
||||
/* check if queue contains events we depend on */
|
||||
LIST_FOREACH(event, loop_event, manager->events) {
|
||||
/* we already found a later event, earlier can not block us, no need to check again */
|
||||
/* we already found a later event, earlier cannot block us, no need to check again */
|
||||
if (loop_event->seqnum < event->delaying_seqnum)
|
||||
continue;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user