Commit b0ca726585 "rpm: avoid hiding errors from systemd commands" remove hiding errors and output
for other macros, but did not do that for %sysusers_create_package and %tmpfiles_create_package.
This change syncs their behaviour with %sysusers_create and %tmpfiles_create
Signed-off-by: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
The last line in this macros was actually "SYSTEMD_INLINE_EOF " with a space at the end,
but the shell was instructed to look for a line without space.
Macros %sysusers_create_inline and %tmpfiles_create_inline did not have this mistake.
An example:
[root@rosa-2019 bind-server]# cat /etc/passwd | grep named
[root@rosa-2019 bind-server]# cat /tmp/bs
systemd-sysusers --replace=/usr/lib/sysusers.d/named.conf - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || :
u named - "BIND DNS Server" /var/lib/named
g named - -
m named named
SYSTEMD_INLINE_EOF
[root@rosa-2019 bind-server]# sh /tmp/bs
/tmp/bs: line 5: warning: here-document at line 1 delimited by end-of-file (wanted `SYSTEMD_INLINE_EOF')
[root@rosa-2019 bind-server]# bash /tmp/bs
/tmp/bs: line 5: warning: here-document at line 1 delimited by end-of-file (wanted `SYSTEMD_INLINE_EOF')
[root@rosa-2019 bind-server]# bash --version
GNU bash, version 5.0.17(1)-release (x86_64-openmandriva-linux-gnu)
The user and group named were NOT created!
Now I remove the trailing space after "SYSTEMD_INLINE_EOF" and rerun:
[root@rosa-2019 bind-server]# sh /tmp/bs
[root@rosa-2019 bind-server]# tail -n 1 /etc/group
named❌485:named
[root@rosa-2019 bind-server]#
The user and group have been created correctly.
Signed-off-by: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
Humans are susceptible to making orthographic errors sometimes. A
misspelled "%systemd_post caek.service" would go unnoticed due to all
output from systemctl being discarded if and when %post runs.
To alleviate this, cease hiding outputs. Then, to account for the
potential absence of systemd from the system, add file checks so as
to not generate a "command not found" error.
Invoking %systemd_tmpfiles (in %post) without any arguments, while
possible, will cause systemd-tmpfiles to process the entire system
configuration, rather than just the newly installed configuration
files. In https://github.com/systemd/systemd/pull/12048, it was
established that processing everything constitutes unusual practice,
and should be flagged as a mistake at build time.
Furthermore, invoking %systemd_post without any arguments will cause
the underlying `systemctl preset` to outright return an error ("Too
few arguments") when run. This can be flagged during build time in
the same manner.
As I have found no ways to successfully nest %if clauses inside a
macro[1], I am helping myself by reusing the recursive variable
expansion technique pioneered in [2].
Now, when %systemd_post or %systemd_tmpfiles is incorrectly used,
rpm gives accurate line number reporting, too:
error: This macro requires some arguments
error: line 11: %{systemd_post}
error: This macro requires two arguments
error: line 13: %{tmpfiles_create_package meh more more}
[1] what has been tried: %{expand:%%if "%#" == 0 \\\
%%{error:you have given me %# args} \\\
%%endif}
[2] http://git.savannah.gnu.org/cgit/automake.git/commit/?id=e0bd4af16da88e4c2c61bde42675660eff7dff51
Files which are installed as-is (any .service and other unit files, .conf
files, .policy files, etc), are left as is. My assumption is that SPDX
identifiers are not yet that well known, so it's better to retain the
extended header to avoid any doubt.
I also kept any copyright lines. We can probably remove them, but it'd nice to
obtain explicit acks from all involved authors before doing that.
It's common for sysusers files to contain quotes (in particular around the
comment/GECOS field), and using echo "..." is very likely to not work properly
in that case. Let's use <<EOF redirection. It's not bulletproof, but should
work in general.
For quite a while now, there have been file triggers to handle
automatically setting up service units in upstream systemd. However,
most of the actions being done by these macros upon files can be set up
as RPM file triggers.
In fact, in Mageia, we had been doing this for most of these. In particular,
we have file triggers in place for sysusers, tmpfiles, hwdb, and the journal.
This change adds Lua versions of the original file triggers used in Mageia,
based on the existing Lua-based file triggers for service units.
In addition, we can also have useful file triggers for udev rules, sysctl
directives, and binfmt directives. These are based on the other existing
file triggers.
I expect that this will be mostly obsoleted by transfiletriggers that
(I hope) we will soon add. But let's do this for completeness anyway.
I'm keeping the description of the macro a bit vague, since I expect
that it'll be changed when transfiletriggers are added.
This is close to %sysusers_create_inline and %sysusers_create that we had
already, but expects a file name and uses --replace= to implement proper
priority.
This is used like:
%sysusers_create_package %{name} %SOURCE1
where %SOURCE1 is a file with called %{name}.conf that will be installed
into /usr/lib/sysusers.d/.
The tough part is that the file needs to be available before %prep,
i.e. outside of the source tarball. This is because the spec file is
parsed (and any macros expanded), before the sources are unpackaged.
v2:
- disallow the case case when --config-name= is given but there are no
positional args. Most likely this would be a user error, so at least for now
forbid it.
v3:
- replace --config-name= with --target=
- drop quotes around %1 and %2 — if necessary, the caller should add
those.
v4:
- replace --target with --replace
- add a big comment
Environment file generators are a lot like unit file generators, but not
exactly:
1. environment file generators are run for each manager instance, and their
output is (or at least can be) individualized.
The generators themselves are system-wide, the same for all users.
2. environment file generators are run sequentially, in priority order.
Thus, the lifetime of those files is tied to lifecycle of the manager
instance. Because generators are run sequentially, later generators can use or
modify the output of earlier generators.
Each generator is run with no arguments, and the whole state is stored in the
environment variables. The generator can echo a set of variable assignments to
standard output:
VAR_A=something
VAR_B=something else
This output is parsed, and the next and subsequent generators run with those
updated variables in the environment. After the last generator is done, the
environment that the manager itself exports is updated.
Each generator must return 0, otherwise the output is ignored.
The generators in */user-env-generator are for the user session managers,
including root, and the ones in */system-env-generator are for pid1.
To remove the hard dependency on systemd, for packages, which function
without a running systemd the %systemd_ordering macro can be used to
ensure ordering in the rpm transaction. %systemd_ordering makes sure,
the systemd rpm is installed prior to the package, so the %pre/%post
scripts can execute the systemd parts.
Installing systemd afterwards though, does not result in the same outcome.
Escape "--user" and "--global" arguments with "\\" since rpm treats
arguments starting with "-" as macro options which causes "Unknown
option" rpm error.
Use %{expand:...} to force expansion of the inner macro. Otherwise %{?*}
is recursively defined as "\--user \--global {%?*}" which causes
"Too many levels of recursion in macro expansion" rpm error.
Thanks to Michael Mráka for helping me fix the above issues.
This uses new functionality added in rpm 4.13. Instead of doing
one daemon-reload per packages, we do just one or two
(When both installing and uninstalling packages, we do
two. Unfortunately this also includes the common case of upgrades.
When only installing or when only installing, we do just one.)
New file triggers.systemd can be built, but the contents have
to be copied into the rpm spec file by hand. Using %{load} does
not seem to work. It can serve as documentation.
This allows encoding users to create directly in %pre, which is
necessary so that files owned by the RPM can be assigned to the right
users/groups.
This new macro does create a redundancy, as user definitions for all
users that shall own files need to to be listed twice, once with this
new macro, and then secondly, in the sysusers file shipped with the
package. But there's little way around that, as the users of this type
need to exist before we install the first file, but we actually want to
ship the user information in a file.
With this in place RPMs can make sure that whatever they drop in is
immeidately applied, and not delayed until next reboot.
This also moves systemd-sysusers back to /usr/bin, since hardcoding the
path to /usr/lib in the macros would mean compatibility breaks in
future, should we turn sysusers into a command that is actually OK for
people to call directly. And given that that is quite likely to happen
(since it is useful to prepare images with its --root= switch), let's
just prepare for it.
this gives us a little bit more freedom to move things around later on,
as we don't hardcode the systemd paths in old RPMs that shall work with
new systemds.
More specifically this adds a number of macros that resolve to
directories for udev rules, hwdb entries, tmpfiles and sysctl.
Thsi also includes three new macros for rebuilding the hwbd/catalog
index when a package drops in new files
Let's try to standardize a bit the RPM macros used for
installing/uninstalling services.
This only covers the non-SysV compat bits, since that tends to vary
widely between the various distros.
Usage:
Add %{?systemd_requires} to the header of the spec file. And then:
%post
%systemd_post foobar.service
%preun
%systemd_preun foobar.service
%postun
%systemd_postun foobar.service
And, instead of the latter, in case the service shall be restarted on updates:
%postun
%systemd_postun_restart foobar.service