Linux Archive

Linux Archive (http://www.linux-archive.org/)
-   ArchLinux Development (http://www.linux-archive.org/archlinux-development/)
-   -   systemd service files policy (http://www.linux-archive.org/archlinux-development/697034-systemd-service-files-policy.html)

Tom Gundersen 08-23-2012 03:32 PM

systemd service files policy
 
Hi guys,

We are hard at work adding systemd service files, and I thought it
might be worth discussing a few guidelines for how to do it (should
eventually end up in the wiki I suppose, but thought it would be best
to start the discussion here).



I propose (based on input gathered on IRC) something like:


1) Use the upstream service files whenever they exist.

2) Don't do anything Arch-specific, if possible. This will maximize
our chances of not having to change behavior in the future once the
service file is provided by upstream. In particular avoid
EnvironmentFile= especially if it points to the Arch-specific
/etc/conf.d/*.

Not using an EnvironmentFile= is ok if:

2a) either the daemon has its own configuration file where the same
settings can be specified.
2b) the default service file "just works" in the most common case.
Users who want to change the behavior should then override the default
service file.

If it is not possible to provide a sane default service file, I
suppose we should discuss it on a case-by-case basis.





A few comments about service files (assuming we just want to preserve
roughly the current behavior and not do anything fancy (if you want to
get fancy, I'll assume you know what you are doing)):

3) If your service requires the network to be configured before it
starts use After=network.target. Do not use
Wants/Requires=network.target.

4) Use Type=forking, unless you know it is not necessary. Most daemons
use double-forking to signal that they are ready, so to minimize the
chance of problems it is probably safest to use this mode. To make
sure that systemd is able to figure out which process is the main
process, it is best to tell the daemon to write a pidfile and point
systemd to it using PIDFile=. (If the daemon in question is dbus or
socket activated, that's a different matter, but I guess that is only
the case for the minority of daemons).

5) Our rc scripts do not support dependencies, but with systemd we
should add them where necessary. The most typical case is that A
requires the service B to be running before A is started. In that case
add Requires=B and After=B to A. If the dependency is optional then
add Wants=B and After=B instead. Dependencies are typically placed on
services and not on targets (see 3).




Example of a simple conversion:

rc script
=====

#!/bin/bash

. /etc/rc.conf
. /etc/rc.d/functions

case "$1" in
start)
stat_busy "Starting NIS Server"
/usr/sbin/ypserv
if [ $? -gt 0 ]; then
stat_fail
else
add_daemon ypserv
stat_done
fi
;;
stop)
stat_busy "Stopping NIS Server"
killall -q /usr/sbin/ypserv
if [ $? -gt 0 ]; then
stat_fail
else
rm_daemon ypserv
stat_done
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "usage: $0 {start|stop|restart}"
esac

systemd service file
============

[Unit]
Description=NIS/YP (Network Information Service) Server
Requires=rpcbind.service
After=network.target rpcbind.service

[Service]
Type=forking
PIDFile=/run/ypserv.pid
ExecStart=/usr/sbin/ypserv

[Install]
WantedBy=multi-user.target

Sébastien Luttringer 08-30-2012 03:07 PM

systemd service files policy
 
On Thu, Aug 23, 2012 at 5:32 PM, Tom Gundersen <teg@jklm.no> wrote:
> 1) Use the upstream service files whenever they exist.
This should be a SHOULD and not a MUST. Some service files can be
poorly implemented or some deps are missing (e.g. your point 5) and be
overloaded by maintainer.

Of course we want to push it upstream, like I've done with sslh, and
now people add improvments upstream.

> 2) Don't do anything Arch-specific, if possible. This will maximize
> our chances of not having to change behavior in the future once the
> service file is provided by upstream. In particular avoid
> EnvironmentFile= especially if it points to the Arch-specific
> /etc/conf.d/*.
>
> Not using an EnvironmentFile= is ok if:
I agree. I will gradually fix my packages.

> 3) If your service requires the network to be configured before it
> starts use After=network.target. Do not use
> Wants/Requires=network.target.
I agree.

> 4) Use Type=forking, unless you know it is not necessary. Most daemons
> use double-forking to signal that they are ready, so to minimize the
> chance of problems it is probably safest to use this mode. To make
> sure that systemd is able to figure out which process is the main
> process, it is best to tell the daemon to write a pidfile and point
> systemd to it using PIDFile=. (If the daemon in question is dbus or
> socket activated, that's a different matter, but I guess that is only
> the case for the minority of daemons).

I think we should _not_ use Type=Forking, except when it's the only choice.
Systemd prefer not use forking type and it would be better to follow this.

Advantage to avoid forking can be read here [1] and in many others
places. In short:
- Disable forking may save each process to fork, setsid, wirte
pidfiles, close stdin/stdout/stderr.
- Save systemd logic to find main pid.

At first sight there is only pro but some peoples suggest to use
forking for daemons which support foreground mode.
The reason seems to be : systemd consider a unit started once launched
when type=simple, whereas it consider a unit started when program exit
when type=fork.

This can be useful *IF* daemon proceed in a specific order. In other
words, it starts all it has to do and dameonize (double fork, etc)
after.
In most situations[2] daemons are not implemented like this and
daemonize before starting all its services. So there is only cons to
use Type=forking.
An example is fcron[3] (We discuss of this with Dave on IRC last time).

So I think use Type=Forking is not the better recommendation. I would
says : Try to use all other method before Type=Forking.

> 5) Our rc scripts do not support dependencies, but with systemd we
> should add them where necessary. The most typical case is that A
> requires the service B to be running before A is started. In that case
> add Requires=B and After=B to A. If the dependency is optional then
> add Wants=B and After=B instead. Dependencies are typically placed on
> services and not on targets (see 3).
>
I agree too.

[1] http://0pointer.de/blog/projects/systemd.html
[2] It's a feeling not based on statistics.
[3] https://bugs.archlinux.org/task/31248

--
Sébastien "Seblu" Luttringer
www.seblu.net

Tom Gundersen 08-30-2012 03:40 PM

systemd service files policy
 
On Thu, Aug 30, 2012 at 5:07 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
> On Thu, Aug 23, 2012 at 5:32 PM, Tom Gundersen <teg@jklm.no> wrote:
>> 1) Use the upstream service files whenever they exist.
> This should be a SHOULD and not a MUST. Some service files can be
> poorly implemented or some deps are missing (e.g. your point 5) and be
> overloaded by maintainer.

Makes sense. Like with any other part of the packages, we might need
to patch things until they are fixed upstream.

>> 4) Use Type=forking, unless you know it is not necessary. Most daemons
>> use double-forking to signal that they are ready, so to minimize the
>> chance of problems it is probably safest to use this mode. To make
>> sure that systemd is able to figure out which process is the main
>> process, it is best to tell the daemon to write a pidfile and point
>> systemd to it using PIDFile=. (If the daemon in question is dbus or
>> socket activated, that's a different matter, but I guess that is only
>> the case for the minority of daemons).
>
> I think we should _not_ use Type=Forking, except when it's the only choice.
> Systemd prefer not use forking type and it would be better to follow this.

I agree that using anything else than Type=forking is preferable when
possible, but correctness must come first. It is important that
systemd is able to tell when a service is started, so that other
services can order themselves After= it. This is achieved in the
following ways:

Type=simple: not at all, it is assumed that this service may be
considered "started" immediately. Either because it does not provide
any communication channels for other services to connect to, or
because those channels are set up using .socket's (the latter requires
the daemon to contain specific code to deal with systemd, so is not so
common yet).

Type=notify: the daemon will send a signal to systemd when it is
ready, this requires systemd-specific code.

Type=dbus: the daemon is considered ready whenever a given dbus
interface appears on the system bus.

Type=oneshot: this is considered started when it exits (so not
applicable to long-running daemons).

Type=forking: this behaves exactly like traditional daemons: it is
considered started when the first process has double-forked and
exited, it might be necessary to use a PIDFile= so systemd knows which
of the remaining processes is the main one.

As you can tell, all the types but "forking" depends on the daemons
being implemented in a specific way, whereas Type=forking will work if
and only if the old rc scripts worked correctly. So use something else
if you know what you are doing, but as a general principle, I'd say
that Type=forking is "safe" and anything else is an optimization we
might leave for upstream to do, or get back to later once we have
finished creating all the services.

> In most situations[2] daemons are not implemented like this and
> daemonize before starting all its services. So there is only cons to
> use Type=forking.

If that is indeed the case, there is no point to using Type=forking.
However, that would be a bug which also affects our old initscripts
(and any other sysvinit-style init), so I would be surprised if it is
very common.

-t

Rashif Ray Rahman 08-30-2012 03:52 PM

systemd service files policy
 
On 30 August 2012 23:40, Tom Gundersen <teg@jklm.no> wrote:
> On Thu, Aug 30, 2012 at 5:07 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
>> On Thu, Aug 23, 2012 at 5:32 PM, Tom Gundersen <teg@jklm.no> wrote:
>>> 1) Use the upstream service files whenever they exist.
>> This should be a SHOULD and not a MUST. Some service files can be
>> poorly implemented or some deps are missing (e.g. your point 5) and be
>> overloaded by maintainer.
>
> Makes sense. Like with any other part of the packages, we might need
> to patch things until they are fixed upstream.

What concerns me is the "overloaded by maintainer" part. For e.g.,
what if the maintainer disagrees with one single approach that appears
to come from our distribution? Do we then have to keep our own service
file "fork"?


--
GPG/PGP ID: C0711BF1

Tom Gundersen 08-30-2012 04:04 PM

systemd service files policy
 
On Thu, Aug 30, 2012 at 5:52 PM, Rashif Ray Rahman <schiv@archlinux.org> wrote:
> What concerns me is the "overloaded by maintainer" part. For e.g.,
> what if the maintainer disagrees with one single approach that appears
> to come from our distribution? Do we then have to keep our own service
> file "fork"?

I'd say we should treat it as we always do: follow upstream whenever
possible and only patch critical bugs.

-t

Sébastien Luttringer 08-31-2012 12:06 PM

systemd service files policy
 
On Thu, Aug 30, 2012 at 5:40 PM, Tom Gundersen <teg@jklm.no> wrote:
> On Thu, Aug 30, 2012 at 5:07 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
>> On Thu, Aug 23, 2012 at 5:32 PM, Tom Gundersen <teg@jklm.no> wrote:
>> I think we should _not_ use Type=Forking, except when it's the only choice.
>> Systemd prefer not use forking type and it would be better to follow this.
>
> I agree that using anything else than Type=forking is preferable when
> possible, but correctness must come first.
That was I think we should underline in our wiki.

> It is important that
> systemd is able to tell when a service is started, so that other
> services can order themselves After= it.
Sure.

--
Sébastien "Seblu" Luttringer
www.seblu.net


All times are GMT. The time now is 06:49 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.