[arch-dev-public] [RFC] systemd service files policy

Tom Gundersen teg at jklm.no
Thu Aug 23 11:32:44 EDT 2012


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


More information about the arch-dev-public mailing list