[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: restarting instanced systemd services on upgrade



On Mon, 09 Nov 2020 at 12:24:03 +0900, Norbert Preining wrote:
[Paul wrote]:
> > These are not "systemd user services" as described in your email subject, they are
> > per-user instances of systemd system services.

How to tell: run systemd-cgls and look at where they appear in the tree.
Everything below user@${uid}.service is a user service. Everything below
session-${n}.service is a non-systemd-managed user process. The rest are
system services or non-systemd-managed system processes.

Normally, the only system service that is instanced per-user is
user@.service, which is the `systemd --user` that is started by
systemd-logind on behalf of each user.

It is unusual to instance other system services on a per-user basis,
because there is already `systemd --user` available to manage per-user
services (like dbus-daemon --session, pulseaudio, gpg-agent).

When you have an instanced service, systemd doesn't know what the
instance represents: that's private to the service itself. It's often
an arbitrary instance name (the Debian packages for openvpn, postfix,
tor and openarena-server are examples of this), but it could be some
related resource like a virtual console (getty@tty2.service).

> > package, it seems you need a onedrive.service in addition to
> 
> We ship also one onedrive.service. This is used when a user starts
> 	systemctl --user onedrive

That's a user-service, which is unrelated (it's managed by a different
per-user instance of systemd, and is not visible to the system-wide
instance). I think Paul means you might need a *system service* named
onedrive.service.

For example, have a look at postfix and openvpn. They have a non-instanced
service that just runs /bin/true, and an instanced service that runs
the actual daemon. The instanced service postfix@.service is marked
as PartOf=postfix.service, which means that when you stop or restart
postfix.service, systemd will automatically stop or restart all the
instances.

However, I think systemd upstream would probably say that this is a hack,
because a no-op service that runs /bin/true is not really a service,
and that the non-instanced service should be replaced by a non-instanced
target (for example postfix@.service PartOf=postfix.target).

Unlike services, targets are specifically designed to be used to group
units together, without starting daemons or other processes themselves.
For example, /lib/systemd/system/systemd-nspawn@.service has
PartOf=machines.target, which means that `systemctl restart machines.target`
will restart all services matching systemd-nspawn@foo.service; and
similarly the cron-* services, targets, etc. installed by the systemd-cron
package are PartOf=cron.target.

I think most Debian package maintainers have used no-op non-instanced
services because that gives them the most obvious migration path
from sysv-rc services to systemd services (sysv-rc has no concept of
instances, targets or user services, only an equivalent of systemd
non-instanced system services), or because debhelper historically did
not have full support for non-service units. It should be possible to
use targets instead since at least dh compat level 11 (the point at which
responsibility for handling systemd services moved from dh_installinit,
dh_systemd_enable and dh_systemd_start to dh_installsystemd).

> What about the following code in postinst?
>     restart_units="`systemctl list-units --no-legend --type=service --state=running 'onedrive*' | awk '{print$1}'`"
>     if ! [ "x$restart_units" = "x" ] ; then
>       echo -n "Restarting running Onedrive processes ... "
>       for unit in $restart_units ; do
>         echo -n "$unit "
>         systemctl restart "$unit"
>       done
>       echo "."
>     fi
> Would this be against any policy?

It would be against the policy of "if you write less code, you'll have
fewer bugs"? :-)

(In addition to the units you intended, this would restart an unrelated
onedriveperchild.service or onedrivetorulethemall.service, which could
result in data loss.)

It would be better to give onedrive@.service PartOf=onedrive.target, and
have the postinst restart onedrive.target - which I think dh_installsystemd
will set up automatically, so you might not have to write any code for it
at all, other than creating the .target unit.

    smcv


Reply to: