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:
Zbigniew Jędrzejewski-Szmek 2018-02-09 17:08:23 +01:00 committed by GitHub
commit 91761b1846
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 439 additions and 260 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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]' \

View file

@ -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(&times.unitsload_start_time, times.reverse_offset);
subtract_timestamp(&times.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 },

View file

@ -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;
}
}

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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:

View file

@ -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);

View file

@ -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"

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;