Add Makefile and a bit of documentation
parent
ceb4a4dec5
commit
a340e9a285
@ -0,0 +1,21 @@
|
|||||||
|
CC:=gcc
|
||||||
|
WARNINGS:=-Wall -Wextra -Wpedantic
|
||||||
|
CCFLAGS:=$(WARNINGS) -g
|
||||||
|
LINKER:=gcc
|
||||||
|
LINKFLAGS:=
|
||||||
|
|
||||||
|
all: zapoctak
|
||||||
|
|
||||||
|
zapoctak: main.x
|
||||||
|
mv main.x zapoctak
|
||||||
|
|
||||||
|
%.x: %.o
|
||||||
|
$(LINKER) -o $@ $(LINKFLAGS) $^
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) -c -o $@ $(CCFLAGS) $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -v *.x *.o *.dump a.out 2>/dev/null
|
||||||
|
|
||||||
|
.PHONY: all clean
|
@ -0,0 +1,525 @@
|
|||||||
|
DAEMON(7) daemon DAEMON(7)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
daemon - Writing and packaging system daemons
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
A daemon is a service process that runs in the background and
|
||||||
|
supervises the system or provides functionality to other processes.
|
||||||
|
Traditionally, daemons are implemented following a scheme originating
|
||||||
|
in SysV Unix. Modern daemons should follow a simpler yet more powerful
|
||||||
|
scheme (here called "new-style" daemons), as implemented by systemd(1).
|
||||||
|
This manual page covers both schemes, and in particular includes
|
||||||
|
recommendations for daemons that shall be included in the systemd init
|
||||||
|
system.
|
||||||
|
|
||||||
|
SysV Daemons
|
||||||
|
When a traditional SysV daemon starts, it should execute the following
|
||||||
|
steps as part of the initialization. Note that these steps are
|
||||||
|
unnecessary for new-style daemons (see below), and should only be
|
||||||
|
implemented if compatibility with SysV is essential.
|
||||||
|
|
||||||
|
1. Close all open file descriptors except standard input, output, and
|
||||||
|
error (i.e. the first three file descriptors 0, 1, 2). This ensures
|
||||||
|
that no accidentally passed file descriptor stays around in the
|
||||||
|
daemon process. On Linux, this is best implemented by iterating
|
||||||
|
through /proc/self/fd, with a fallback of iterating from file
|
||||||
|
descriptor 3 to the value returned by getrlimit() for
|
||||||
|
RLIMIT_NOFILE.
|
||||||
|
|
||||||
|
2. Reset all signal handlers to their default. This is best done by
|
||||||
|
iterating through the available signals up to the limit of _NSIG
|
||||||
|
and resetting them to SIG_DFL.
|
||||||
|
|
||||||
|
3. Reset the signal mask using sigprocmask().
|
||||||
|
|
||||||
|
4. Sanitize the environment block, removing or resetting environment
|
||||||
|
variables that might negatively impact daemon runtime.
|
||||||
|
|
||||||
|
5. Call fork(), to create a background process.
|
||||||
|
|
||||||
|
6. In the child, call setsid() to detach from any terminal and create
|
||||||
|
an independent session.
|
||||||
|
|
||||||
|
7. In the child, call fork() again, to ensure that the daemon can
|
||||||
|
never re-acquire a terminal again.
|
||||||
|
|
||||||
|
8. Call exit() in the first child, so that only the second child (the
|
||||||
|
actual daemon process) stays around. This ensures that the daemon
|
||||||
|
process is re-parented to init/PID 1, as all daemons should be.
|
||||||
|
|
||||||
|
9. In the daemon process, connect /dev/null to standard input, output,
|
||||||
|
and error.
|
||||||
|
|
||||||
|
10. In the daemon process, reset the umask to 0, so that the file modes
|
||||||
|
passed to open(), mkdir() and suchlike directly control the access
|
||||||
|
mode of the created files and directories.
|
||||||
|
|
||||||
|
11. In the daemon process, change the current directory to the root
|
||||||
|
directory (/), in order to avoid that the daemon involuntarily
|
||||||
|
blocks mount points from being unmounted.
|
||||||
|
|
||||||
|
12. In the daemon process, write the daemon PID (as returned by
|
||||||
|
getpid()) to a PID file, for example /run/foobar.pid (for a
|
||||||
|
hypothetical daemon "foobar") to ensure that the daemon cannot be
|
||||||
|
started more than once. This must be implemented in race-free
|
||||||
|
fashion so that the PID file is only updated when it is verified at
|
||||||
|
the same time that the PID previously stored in the PID file no
|
||||||
|
longer exists or belongs to a foreign process.
|
||||||
|
|
||||||
|
13. In the daemon process, drop privileges, if possible and applicable.
|
||||||
|
|
||||||
|
14. From the daemon process, notify the original process started that
|
||||||
|
initialization is complete. This can be implemented via an unnamed
|
||||||
|
pipe or similar communication channel that is created before the
|
||||||
|
first fork() and hence available in both the original and the
|
||||||
|
daemon process.
|
||||||
|
|
||||||
|
15. Call exit() in the original process. The process that invoked the
|
||||||
|
daemon must be able to rely on that this exit() happens after
|
||||||
|
initialization is complete and all external communication channels
|
||||||
|
are established and accessible.
|
||||||
|
|
||||||
|
The BSD daemon() function should not be used, as it implements only a
|
||||||
|
subset of these steps.
|
||||||
|
|
||||||
|
A daemon that needs to provide compatibility with SysV systems should
|
||||||
|
implement the scheme pointed out above. However, it is recommended to
|
||||||
|
make this behavior optional and configurable via a command line
|
||||||
|
argument to ease debugging as well as to simplify integration into
|
||||||
|
systems using systemd.
|
||||||
|
|
||||||
|
New-Style Daemons
|
||||||
|
Modern services for Linux should be implemented as new-style daemons.
|
||||||
|
This makes it easier to supervise and control them at runtime and
|
||||||
|
simplifies their implementation.
|
||||||
|
|
||||||
|
For developing a new-style daemon, none of the initialization steps
|
||||||
|
recommended for SysV daemons need to be implemented. New-style init
|
||||||
|
systems such as systemd make all of them redundant. Moreover, since
|
||||||
|
some of these steps interfere with process monitoring, file descriptor
|
||||||
|
passing and other functionality of the init system, it is recommended
|
||||||
|
not to execute them when run as new-style service.
|
||||||
|
|
||||||
|
Note that new-style init systems guarantee execution of daemon
|
||||||
|
processes in a clean process context: it is guaranteed that the
|
||||||
|
environment block is sanitized, that the signal handlers and mask is
|
||||||
|
reset and that no left-over file descriptors are passed. Daemons will
|
||||||
|
be executed in their own session, with standard input connected to
|
||||||
|
/dev/null and standard output/error connected to the systemd-
|
||||||
|
journald.service(8) logging service, unless otherwise configured. The
|
||||||
|
umask is reset.
|
||||||
|
|
||||||
|
It is recommended for new-style daemons to implement the following:
|
||||||
|
|
||||||
|
1. If SIGTERM is received, shut down the daemon and exit cleanly.
|
||||||
|
|
||||||
|
2. If SIGHUP is received, reload the configuration files, if this
|
||||||
|
applies.
|
||||||
|
|
||||||
|
3. Provide a correct exit code from the main daemon process, as this
|
||||||
|
is used by the init system to detect service errors and problems.
|
||||||
|
It is recommended to follow the exit code scheme as defined in the
|
||||||
|
LSB recommendations for SysV init scripts[1].
|
||||||
|
|
||||||
|
4. If possible and applicable, expose the daemon's control interface
|
||||||
|
via the D-Bus IPC system and grab a bus name as last step of
|
||||||
|
initialization.
|
||||||
|
|
||||||
|
5. For integration in systemd, provide a .service unit file that
|
||||||
|
carries information about starting, stopping and otherwise
|
||||||
|
maintaining the daemon. See systemd.service(5) for details.
|
||||||
|
|
||||||
|
6. As much as possible, rely on the init system's functionality to
|
||||||
|
limit the access of the daemon to files, services and other
|
||||||
|
resources, i.e. in the case of systemd, rely on systemd's resource
|
||||||
|
limit control instead of implementing your own, rely on systemd's
|
||||||
|
privilege dropping code instead of implementing it in the daemon,
|
||||||
|
and similar. See systemd.exec(5) for the available controls.
|
||||||
|
|
||||||
|
7. If D-Bus is used, make your daemon bus-activatable by supplying a
|
||||||
|
D-Bus service activation configuration file. This has multiple
|
||||||
|
advantages: your daemon may be started lazily on-demand; it may be
|
||||||
|
started in parallel to other daemons requiring it — which maximizes
|
||||||
|
parallelization and boot-up speed; your daemon can be restarted on
|
||||||
|
failure without losing any bus requests, as the bus queues requests
|
||||||
|
for activatable services. See below for details.
|
||||||
|
|
||||||
|
8. If your daemon provides services to other local processes or remote
|
||||||
|
clients via a socket, it should be made socket-activatable
|
||||||
|
following the scheme pointed out below. Like D-Bus activation, this
|
||||||
|
enables on-demand starting of services as well as it allows
|
||||||
|
improved parallelization of service start-up. Also, for state-less
|
||||||
|
protocols (such as syslog, DNS), a daemon implementing socket-based
|
||||||
|
activation can be restarted without losing a single request. See
|
||||||
|
below for details.
|
||||||
|
|
||||||
|
9. If applicable, a daemon should notify the init system about startup
|
||||||
|
completion or status updates via the sd_notify(3) interface.
|
||||||
|
|
||||||
|
10. Instead of using the syslog() call to log directly to the system
|
||||||
|
syslog service, a new-style daemon may choose to simply log to
|
||||||
|
standard error via fprintf(), which is then forwarded to syslog by
|
||||||
|
the init system. If log levels are necessary, these can be encoded
|
||||||
|
by prefixing individual log lines with strings like "<4>" (for log
|
||||||
|
level 4 "WARNING" in the syslog priority scheme), following a
|
||||||
|
similar style as the Linux kernel's printk() level system. For
|
||||||
|
details, see sd-daemon(3) and systemd.exec(5).
|
||||||
|
|
||||||
|
These recommendations are similar but not identical to the Apple MacOS
|
||||||
|
X Daemon Requirements[2].
|
||||||
|
|
||||||
|
ACTIVATION
|
||||||
|
New-style init systems provide multiple additional mechanisms to
|
||||||
|
activate services, as detailed below. It is common that services are
|
||||||
|
configured to be activated via more than one mechanism at the same
|
||||||
|
time. An example for systemd: bluetoothd.service might get activated
|
||||||
|
either when Bluetooth hardware is plugged in, or when an application
|
||||||
|
accesses its programming interfaces via D-Bus. Or, a print server
|
||||||
|
daemon might get activated when traffic arrives at an IPP port, or when
|
||||||
|
a printer is plugged in, or when a file is queued in the printer spool
|
||||||
|
directory. Even for services that are intended to be started on system
|
||||||
|
bootup unconditionally, it is a good idea to implement some of the
|
||||||
|
various activation schemes outlined below, in order to maximize
|
||||||
|
parallelization. If a daemon implements a D-Bus service or listening
|
||||||
|
socket, implementing the full bus and socket activation scheme allows
|
||||||
|
starting of the daemon with its clients in parallel (which speeds up
|
||||||
|
boot-up), since all its communication channels are established already,
|
||||||
|
and no request is lost because client requests will be queued by the
|
||||||
|
bus system (in case of D-Bus) or the kernel (in case of sockets) until
|
||||||
|
the activation is completed.
|
||||||
|
|
||||||
|
Activation on Boot
|
||||||
|
Old-style daemons are usually activated exclusively on boot (and
|
||||||
|
manually by the administrator) via SysV init scripts, as detailed in
|
||||||
|
the LSB Linux Standard Base Core Specification[1]. This method of
|
||||||
|
activation is supported ubiquitously on Linux init systems, both
|
||||||
|
old-style and new-style systems. Among other issues, SysV init scripts
|
||||||
|
have the disadvantage of involving shell scripts in the boot process.
|
||||||
|
New-style init systems generally employ updated versions of activation,
|
||||||
|
both during boot-up and during runtime and using more minimal service
|
||||||
|
description files.
|
||||||
|
|
||||||
|
In systemd, if the developer or administrator wants to make sure that a
|
||||||
|
service or other unit is activated automatically on boot, it is
|
||||||
|
recommended to place a symlink to the unit file in the .wants/
|
||||||
|
directory of either multi-user.target or graphical.target, which are
|
||||||
|
normally used as boot targets at system startup. See systemd.unit(5)
|
||||||
|
for details about the .wants/ directories, and systemd.special(7) for
|
||||||
|
details about the two boot targets.
|
||||||
|
|
||||||
|
Socket-Based Activation
|
||||||
|
In order to maximize the possible parallelization and robustness and
|
||||||
|
simplify configuration and development, it is recommended for all
|
||||||
|
new-style daemons that communicate via listening sockets to employ
|
||||||
|
socket-based activation. In a socket-based activation scheme, the
|
||||||
|
creation and binding of the listening socket as primary communication
|
||||||
|
channel of daemons to local (and sometimes remote) clients is moved out
|
||||||
|
of the daemon code and into the init system. Based on per-daemon
|
||||||
|
configuration, the init system installs the sockets and then hands them
|
||||||
|
off to the spawned process as soon as the respective daemon is to be
|
||||||
|
started. Optionally, activation of the service can be delayed until the
|
||||||
|
first inbound traffic arrives at the socket to implement on-demand
|
||||||
|
activation of daemons. However, the primary advantage of this scheme is
|
||||||
|
that all providers and all consumers of the sockets can be started in
|
||||||
|
parallel as soon as all sockets are established. In addition to that,
|
||||||
|
daemons can be restarted with losing only a minimal number of client
|
||||||
|
transactions, or even any client request at all (the latter is
|
||||||
|
particularly true for state-less protocols, such as DNS or syslog),
|
||||||
|
because the socket stays bound and accessible during the restart, and
|
||||||
|
all requests are queued while the daemon cannot process them.
|
||||||
|
|
||||||
|
New-style daemons which support socket activation must be able to
|
||||||
|
receive their sockets from the init system instead of creating and
|
||||||
|
binding them themselves. For details about the programming interfaces
|
||||||
|
for this scheme provided by systemd, see sd_listen_fds(3) and sd-
|
||||||
|
daemon(3). For details about porting existing daemons to socket-based
|
||||||
|
activation, see below. With minimal effort, it is possible to implement
|
||||||
|
socket-based activation in addition to traditional internal socket
|
||||||
|
creation in the same codebase in order to support both new-style and
|
||||||
|
old-style init systems from the same daemon binary.
|
||||||
|
|
||||||
|
systemd implements socket-based activation via .socket units, which are
|
||||||
|
described in systemd.socket(5). When configuring socket units for
|
||||||
|
socket-based activation, it is essential that all listening sockets are
|
||||||
|
pulled in by the special target unit sockets.target. It is recommended
|
||||||
|
to place a WantedBy=sockets.target directive in the "[Install]" section
|
||||||
|
to automatically add such a dependency on installation of a socket
|
||||||
|
unit. Unless DefaultDependencies=no is set, the necessary ordering
|
||||||
|
dependencies are implicitly created for all socket units. For more
|
||||||
|
information about sockets.target, see systemd.special(7). It is not
|
||||||
|
necessary or recommended to place any additional dependencies on socket
|
||||||
|
units (for example from multi-user.target or suchlike) when one is
|
||||||
|
installed in sockets.target.
|
||||||
|
|
||||||
|
Bus-Based Activation
|
||||||
|
When the D-Bus IPC system is used for communication with clients,
|
||||||
|
new-style daemons should employ bus activation so that they are
|
||||||
|
automatically activated when a client application accesses their IPC
|
||||||
|
interfaces. This is configured in D-Bus service files (not to be
|
||||||
|
confused with systemd service unit files!). To ensure that D-Bus uses
|
||||||
|
systemd to start-up and maintain the daemon, use the SystemdService=
|
||||||
|
directive in these service files to configure the matching systemd
|
||||||
|
service for a D-Bus service. e.g.: For a D-Bus service whose D-Bus
|
||||||
|
activation file is named org.freedesktop.RealtimeKit.service, make sure
|
||||||
|
to set SystemdService=rtkit-daemon.service in that file to bind it to
|
||||||
|
the systemd service rtkit-daemon.service. This is needed to make sure
|
||||||
|
that the daemon is started in a race-free fashion when activated via
|
||||||
|
multiple mechanisms simultaneously.
|
||||||
|
|
||||||
|
Device-Based Activation
|
||||||
|
Often, daemons that manage a particular type of hardware should be
|
||||||
|
activated only when the hardware of the respective kind is plugged in
|
||||||
|
or otherwise becomes available. In a new-style init system, it is
|
||||||
|
possible to bind activation to hardware plug/unplug events. In systemd,
|
||||||
|
kernel devices appearing in the sysfs/udev device tree can be exposed
|
||||||
|
as units if they are tagged with the string "systemd". Like any other
|
||||||
|
kind of unit, they may then pull in other units when activated (i.e.
|
||||||
|
plugged in) and thus implement device-based activation. systemd
|
||||||
|
dependencies may be encoded in the udev database via the SYSTEMD_WANTS=
|
||||||
|
property. See systemd.device(5) for details. Often, it is nicer to pull
|
||||||
|
in services from devices only indirectly via dedicated targets.
|
||||||
|
Example: Instead of pulling in bluetoothd.service from all the various
|
||||||
|
bluetooth dongles and other hardware available, pull in
|
||||||
|
bluetooth.target from them and bluetoothd.service from that target.
|
||||||
|
This provides for nicer abstraction and gives administrators the option
|
||||||
|
to enable bluetoothd.service via controlling a bluetooth.target.wants/
|
||||||
|
symlink uniformly with a command like enable of systemctl(1) instead of
|
||||||
|
manipulating the udev ruleset.
|
||||||
|
|
||||||
|
Path-Based Activation
|
||||||
|
Often, runtime of daemons processing spool files or directories (such
|
||||||
|
as a printing system) can be delayed until these file system objects
|
||||||
|
change state, or become non-empty. New-style init systems provide a way
|
||||||
|
to bind service activation to file system changes. systemd implements
|
||||||
|
this scheme via path-based activation configured in .path units, as
|
||||||
|
outlined in systemd.path(5).
|
||||||
|
|
||||||
|
Timer-Based Activation
|
||||||
|
Some daemons that implement clean-up jobs that are intended to be
|
||||||
|
executed in regular intervals benefit from timer-based activation. In
|
||||||
|
systemd, this is implemented via .timer units, as described in
|
||||||
|
systemd.timer(5).
|
||||||
|
|
||||||
|
Other Forms of Activation
|
||||||
|
Other forms of activation have been suggested and implemented in some
|
||||||
|
systems. However, there are often simpler or better alternatives, or
|
||||||
|
they can be put together of combinations of the schemes above. Example:
|
||||||
|
Sometimes, it appears useful to start daemons or .socket units when a
|
||||||
|
specific IP address is configured on a network interface, because
|
||||||
|
network sockets shall be bound to the address. However, an alternative
|
||||||
|
to implement this is by utilizing the Linux IP_FREEBIND socket option,
|
||||||
|
as accessible via FreeBind=yes in systemd socket files (see
|
||||||
|
systemd.socket(5) for details). This option, when enabled, allows
|
||||||
|
sockets to be bound to a non-local, not configured IP address, and
|
||||||
|
hence allows bindings to a particular IP address before it actually
|
||||||
|
becomes available, making such an explicit dependency to the configured
|
||||||
|
address redundant. Another often suggested trigger for service
|
||||||
|
activation is low system load. However, here too, a more convincing
|
||||||
|
approach might be to make proper use of features of the operating
|
||||||
|
system, in particular, the CPU or I/O scheduler of Linux. Instead of
|
||||||
|
scheduling jobs from userspace based on monitoring the OS scheduler, it
|
||||||
|
is advisable to leave the scheduling of processes to the OS scheduler
|
||||||
|
itself. systemd provides fine-grained access to the CPU and I/O
|
||||||
|
schedulers. If a process executed by the init system shall not
|
||||||
|
negatively impact the amount of CPU or I/O bandwidth available to other
|
||||||
|
processes, it should be configured with CPUSchedulingPolicy=idle and/or
|
||||||
|
IOSchedulingClass=idle. Optionally, this may be combined with
|
||||||
|
timer-based activation to schedule background jobs during runtime and
|
||||||
|
with minimal impact on the system, and remove it from the boot phase
|
||||||
|
itself.
|
||||||
|
|
||||||
|
INTEGRATION WITH SYSTEMD
|
||||||
|
Writing systemd Unit Files
|
||||||
|
When writing systemd unit files, it is recommended to consider the
|
||||||
|
following suggestions:
|
||||||
|
|
||||||
|
1. If possible, do not use the Type=forking setting in service files.
|
||||||
|
But if you do, make sure to set the PID file path using PIDFile=.
|
||||||
|
See systemd.service(5) for details.
|
||||||
|
|
||||||
|
2. If your daemon registers a D-Bus name on the bus, make sure to use
|
||||||
|
Type=dbus in the service file if possible.
|
||||||
|
|
||||||
|
3. Make sure to set a good human-readable description string with
|
||||||
|
Description=.
|
||||||
|
|
||||||
|
4. Do not disable DefaultDependencies=, unless you really know what
|
||||||
|
you do and your unit is involved in early boot or late system
|
||||||
|
shutdown.
|
||||||
|
|
||||||
|
5. Normally, little if any dependencies should need to be defined
|
||||||
|
explicitly. However, if you do configure explicit dependencies,
|
||||||
|
only refer to unit names listed on systemd.special(7) or names
|
||||||
|
introduced by your own package to keep the unit file operating
|
||||||
|
system-independent.
|
||||||
|
|
||||||
|
6. Make sure to include an "[Install]" section including installation
|
||||||
|
information for the unit file. See systemd.unit(5) for details. To
|
||||||
|
activate your service on boot, make sure to add a
|
||||||
|
WantedBy=multi-user.target or WantedBy=graphical.target directive.
|
||||||
|
To activate your socket on boot, make sure to add
|
||||||
|
WantedBy=sockets.target. Usually, you also want to make sure that
|
||||||
|
when your service is installed, your socket is installed too, hence
|
||||||
|
add Also=foo.socket in your service file foo.service, for a
|
||||||
|
hypothetical program foo.
|
||||||
|
|
||||||
|
Installing systemd Service Files
|
||||||
|
At the build installation time (e.g. make install during package
|
||||||
|
build), packages are recommended to install their systemd unit files in
|
||||||
|
the directory returned by pkg-config systemd
|
||||||
|
--variable=systemdsystemunitdir (for system services) or pkg-config
|
||||||
|
systemd --variable=systemduserunitdir (for user services). This will
|
||||||
|
make the services available in the system on explicit request but not
|
||||||
|
activate them automatically during boot. Optionally, during package
|
||||||
|
installation (e.g. rpm -i by the administrator), symlinks should be
|
||||||
|
created in the systemd configuration directories via the enable command
|
||||||
|
of the systemctl(1) tool to activate them automatically on boot.
|
||||||
|
|
||||||
|
Packages using autoconf(1) are recommended to use a configure script
|
||||||
|
excerpt like the following to determine the unit installation path
|
||||||
|
during source configuration:
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG
|
||||||
|
AC_ARG_WITH([systemdsystemunitdir],
|
||||||
|
[AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
|
||||||
|
[with_systemdsystemunitdir=auto])
|
||||||
|
AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
|
||||||
|
def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
|
||||||
|
|
||||||
|
AS_IF([test "x$def_systemdsystemunitdir" = "x"],
|
||||||
|
[AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
|
||||||
|
[AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
|
||||||
|
with_systemdsystemunitdir=no],
|
||||||
|
[with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
|
||||||
|
AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
|
||||||
|
[AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
|
||||||
|
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
|
||||||
|
|
||||||
|
This snippet allows automatic installation of the unit files on systemd
|
||||||
|
machines, and optionally allows their installation even on machines
|
||||||
|
lacking systemd. (Modification of this snippet for the user unit
|
||||||
|
directory is left as an exercise for the reader.)
|
||||||
|
|
||||||
|
Additionally, to ensure that make distcheck continues to work, it is
|
||||||
|
recommended to add the following to the top-level Makefile.am file in
|
||||||
|
automake(1)-based projects:
|
||||||
|
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = \
|
||||||
|
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||||
|
|
||||||
|
Finally, unit files should be installed in the system with an automake
|
||||||
|
excerpt like the following:
|
||||||
|
|
||||||
|
if HAVE_SYSTEMD
|
||||||
|
systemdsystemunit_DATA = \
|
||||||
|
foobar.socket \
|
||||||
|
foobar.service
|
||||||
|
endif
|
||||||
|
|
||||||
|
In the rpm(8) .spec file, use snippets like the following to
|
||||||
|
enable/disable the service during installation/deinstallation. This
|
||||||
|
makes use of the RPM macros shipped along systemd. Consult the
|
||||||
|
packaging guidelines of your distribution for details and the
|
||||||
|
equivalent for other package managers.
|
||||||
|
|
||||||
|
At the top of the file:
|
||||||
|
|
||||||
|
BuildRequires: systemd
|
||||||
|
%{?systemd_requires}
|
||||||
|
|
||||||
|
And as scriptlets, further down:
|
||||||
|
|
||||||
|
%post
|
||||||
|
%systemd_post foobar.service foobar.socket
|
||||||
|
|
||||||
|
%preun
|
||||||
|
%systemd_preun foobar.service foobar.socket
|
||||||
|
|
||||||
|
%postun
|
||||||
|
%systemd_postun
|
||||||
|
|
||||||
|
If the service shall be restarted during upgrades, replace the
|
||||||
|
"%postun" scriptlet above with the following:
|
||||||
|
|
||||||
|
%postun
|
||||||
|
%systemd_postun_with_restart foobar.service
|
||||||
|
|
||||||
|
Note that "%systemd_post" and "%systemd_preun" expect the names of all
|
||||||
|
units that are installed/removed as arguments, separated by spaces.
|
||||||
|
"%systemd_postun" expects no arguments. "%systemd_postun_with_restart"
|
||||||
|
expects the units to restart as arguments.
|
||||||
|
|
||||||
|
To facilitate upgrades from a package version that shipped only SysV
|
||||||
|
init scripts to a package version that ships both a SysV init script
|
||||||
|
and a native systemd service file, use a fragment like the following:
|
||||||
|
|
||||||
|
%triggerun -- foobar < 0.47.11-1
|
||||||
|
if /sbin/chkconfig --level 5 foobar ; then
|
||||||
|
/bin/systemctl --no-reload enable foobar.service foobar.socket >/dev/null 2>&1 || :
|
||||||
|
fi
|
||||||
|
|
||||||
|
Where 0.47.11-1 is the first package version that includes the native
|
||||||
|
unit file. This fragment will ensure that the first time the unit file
|
||||||
|
is installed, it will be enabled if and only if the SysV init script is
|
||||||
|
enabled, thus making sure that the enable status is not changed. Note
|
||||||
|
that chkconfig is a command specific to Fedora which can be used to
|
||||||
|
check whether a SysV init script is enabled. Other operating systems
|
||||||
|
will have to use different commands here.
|
||||||
|
|
||||||
|
PORTING EXISTING DAEMONS
|
||||||
|
Since new-style init systems such as systemd are compatible with
|
||||||
|
traditional SysV init systems, it is not strictly necessary to port
|
||||||
|
existing daemons to the new style. However, doing so offers additional
|
||||||
|
functionality to the daemons as well as simplifying integration into
|
||||||
|
new-style init systems.
|
||||||
|
|
||||||
|
To port an existing SysV compatible daemon, the following steps are
|
||||||
|
recommended:
|
||||||
|
|
||||||
|
1. If not already implemented, add an optional command line switch to
|
||||||
|
the daemon to disable daemonization. This is useful not only for
|
||||||
|
using the daemon in new-style init systems, but also to ease
|
||||||
|
debugging.
|
||||||
|
|
||||||
|
2. If the daemon offers interfaces to other software running on the
|
||||||
|
local system via local AF_UNIX sockets, consider implementing
|
||||||
|
socket-based activation (see above). Usually, a minimal patch is
|
||||||
|
sufficient to implement this: Extend the socket creation in the
|
||||||
|
daemon code so that sd_listen_fds(3) is checked for already passed
|
||||||
|
sockets first. If sockets are passed (i.e. when sd_listen_fds()
|
||||||
|
returns a positive value), skip the socket creation step and use
|
||||||
|
the passed sockets. Secondly, ensure that the file system socket
|
||||||
|
nodes for local AF_UNIX sockets used in the socket-based activation
|
||||||
|
are not removed when the daemon shuts down, if sockets have been
|
||||||
|
passed. Third, if the daemon normally closes all remaining open
|
||||||
|
file descriptors as part of its initialization, the sockets passed
|
||||||
|
from the init system must be spared. Since new-style init systems
|
||||||
|
guarantee that no left-over file descriptors are passed to executed
|
||||||
|
processes, it might be a good choice to simply skip the closing of
|
||||||
|
all remaining open file descriptors if sockets are passed.
|
||||||
|
|
||||||
|
3. Write and install a systemd unit file for the service (and the
|
||||||
|
sockets if socket-based activation is used, as well as a path unit
|
||||||
|
file, if the daemon processes a spool directory), see above for
|
||||||
|
details.
|
||||||
|
|
||||||
|
4. If the daemon exposes interfaces via D-Bus, write and install a
|
||||||
|
D-Bus activation file for the service, see above for details.
|
||||||
|
|
||||||
|
PLACING DAEMON DATA
|
||||||
|
It is recommended to follow the general guidelines for placing package
|
||||||
|
files, as discussed in file-hierarchy(7).
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
systemd(1), sd-daemon(3), sd_listen_fds(3), sd_notify(3), daemon(3),
|
||||||
|
systemd.service(5), file-hierarchy(7)
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
1. LSB recommendations for SysV init scripts
|
||||||
|
http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
|
||||||
|
|
||||||
|
2. Apple MacOS X Daemon Requirements
|
||||||
|
https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html
|
||||||
|
|
||||||
|
systemd 236 DAEMON(7)
|
Loading…
Reference in New Issue