mirror of
https://github.com/AuxXxilium/eudev.git
synced 2024-12-22 15:03:34 +07:00
595 lines
32 KiB
XML
595 lines
32 KiB
XML
<?xml version='1.0'?> <!--*-nxml-*-->
|
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
|
|
|
<!--
|
|
This file is part of systemd.
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
-->
|
|
|
|
<refentry id="daemon">
|
|
|
|
<refentryinfo>
|
|
<title>daemon</title>
|
|
<productname>systemd</productname>
|
|
|
|
<authorgroup>
|
|
<author>
|
|
<contrib>Developer</contrib>
|
|
<firstname>Lennart</firstname>
|
|
<surname>Poettering</surname>
|
|
<email>lennart@poettering.net</email>
|
|
</author>
|
|
</authorgroup>
|
|
</refentryinfo>
|
|
|
|
<refmeta>
|
|
<refentrytitle>daemon</refentrytitle>
|
|
<manvolnum>7</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>daemon</refname>
|
|
<refpurpose>Writing and Packaging System Daemons</refpurpose>
|
|
</refnamediv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>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
|
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>. </para>
|
|
|
|
<refsect2>
|
|
<title>SysV Daemons</title>
|
|
|
|
<para>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.</para>
|
|
|
|
<orderedlist>
|
|
<listitem><para>Close all open file
|
|
descriptors except STDIN, STDOUT,
|
|
STDERR (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
|
|
<filename>/proc/self/fd</filename>,
|
|
with a fallback of iterating from file
|
|
descriptor 3 to the value returned by
|
|
<function>getrlimit()</function> for
|
|
RLIMIT_NOFILE.</para></listitem>
|
|
|
|
<listitem><para>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.</para></listitem>
|
|
|
|
<listitem><para>Reset the signal mask
|
|
using
|
|
<function>sigprocmask()</function>.</para></listitem>
|
|
|
|
<listitem><para>Sanitize the
|
|
environment block, removing or
|
|
resetting environment variables that
|
|
might negatively impact daemon
|
|
runtime.</para></listitem>
|
|
|
|
<listitem><para>Call <function>fork()</function>,
|
|
to create a background
|
|
process.</para></listitem>
|
|
|
|
<listitem><para>In the child, call
|
|
<function>setsid()</function> to
|
|
detach from any terminal and create an
|
|
independent session.</para></listitem>
|
|
|
|
<listitem><para>In the child, call
|
|
<function>fork()</function> again, to
|
|
ensure the daemon can never re-aquire
|
|
a terminal again.</para></listitem>
|
|
|
|
<listitem><para>Call <function>exit()</function> in the
|
|
first child, so that only the second
|
|
child (the actual daemon process)
|
|
stays around. This ensures that the
|
|
daemon process is reparented to
|
|
init/PID 1, as all daemons should
|
|
be.</para></listitem>
|
|
|
|
<listitem><para>In the daemon process,
|
|
connect <filename>/dev/null</filename>
|
|
to STDIN, STDOUT,
|
|
STDERR.</para></listitem>
|
|
|
|
<listitem><para>In the daemon process,
|
|
reset the umask to 0, so that the file
|
|
modes passed to <function>open()</function>, <function>mkdir()</function> and
|
|
suchlike directly control the access
|
|
mode of the created files and
|
|
directories.</para></listitem>
|
|
|
|
<listitem><para>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.</para></listitem>
|
|
|
|
<listitem><para>In the daemon process,
|
|
write the daemon PID (as returned by
|
|
<function>getpid()</function>) to a
|
|
PID file, for example
|
|
<filename>/var/run/foobar.pid</filename>
|
|
(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
|
|
at the same time it is verified that
|
|
the PID previously stored in the PID
|
|
file no longer exists or belongs to a
|
|
foreign process. Commonly some kind of
|
|
file locking is employed to implement
|
|
this logic.</para></listitem>
|
|
|
|
<listitem><para>In the daemon process,
|
|
drop privileges, if possible and
|
|
applicable.</para></listitem>
|
|
|
|
<listitem><para>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
|
|
<function>fork()</function> and hence
|
|
available in both the original and the
|
|
daemon process.</para></listitem>
|
|
|
|
<listitem><para>Call
|
|
<function>exit()</function> in the
|
|
original process. The process that
|
|
invoked the daemon must be able to
|
|
rely that this
|
|
<function>exit()</function> happens
|
|
after initialization is complete and
|
|
all external communication channels
|
|
established and
|
|
accessible.</para></listitem>
|
|
</orderedlist>
|
|
|
|
<para>The BSD <function>daemon()</function> function should not be
|
|
used, as it implements only a subset of these steps.</para>
|
|
|
|
<para>A daemon that needs to provide
|
|
compatibility with SysV systems should
|
|
implement the scheme pointed out
|
|
above. However, it is recommended to make this
|
|
behaviour optional and configurable via a
|
|
command line argument, to ease debugging as
|
|
well as to simplify integration into systems
|
|
using systemd.</para>
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>New-Style Daemons</title>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>Note that new-style init systems
|
|
guarantee execution of daemon processes in
|
|
clean process contexts: 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, and
|
|
STDIN/STDOUT/STDERR connected to
|
|
<filename>/dev/null</filename> unless
|
|
otherwise configured. The umask is reset.</para>
|
|
|
|
<para>It is recommended for new-style daemons
|
|
to implement the following:</para>
|
|
|
|
<orderedlist>
|
|
<listitem><para>If SIGTERM is
|
|
received, shut down the daemon and
|
|
exit cleanly.</para></listitem>
|
|
|
|
<listitem><para>If SIGHUP is received,
|
|
reload the configuration files, if
|
|
this applies.</para></listitem>
|
|
|
|
<listitem><para>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 <ulink
|
|
url="http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html">LSB
|
|
recommendations for SysV init
|
|
scripts</ulink>.</para></listitem>
|
|
|
|
<listitem><para>As much as possible,
|
|
rely on systemd's functionality to
|
|
limit the access of the daemon to
|
|
files, services and other
|
|
resources. i.e. 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
|
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
for the available
|
|
controls.</para></listitem>
|
|
|
|
<listitem><para>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.</para></listitem>
|
|
|
|
<listitem><para>If D-Bus is used, make
|
|
your daemon bus-activatable, via
|
|
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.</para></listitem>
|
|
|
|
<listitem><para>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.</para></listitem>
|
|
|
|
<listitem><para>If applicable a daemon
|
|
should notify the init system about
|
|
startup completion or status updates
|
|
via the
|
|
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
interface.</para></listitem>
|
|
|
|
<listitem><para>Instead of using the
|
|
<function>syslog()</function> call to log directly to the
|
|
system logger, a new-style daemon may
|
|
choose to simply log to STDERR via
|
|
<function>fprintf()</function>, which is then forwarded to
|
|
syslog by the init system. If log
|
|
priorities are necessary these can be
|
|
encoded by prefixing individual log
|
|
lines with strings like "<4>"
|
|
(for log priority 4 "WARNING" in the
|
|
syslog priority scheme), following a
|
|
similar style as the Linux kernel's
|
|
<function>printk()</function> priority system. In fact,
|
|
using this style of logging also
|
|
enables the init system to optionally
|
|
direct all application logging to the
|
|
kernel log buffer (kmsg), as
|
|
accessible via
|
|
<citerefentry><refentrytitle>dmesg</refentrytitle><manvolnum>1</manvolnum></citerefentry>. This
|
|
kind of logging may be enabled by
|
|
setting
|
|
<varname>StandardError=syslog</varname>
|
|
in the service unit file. For details
|
|
see
|
|
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
|
and
|
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
|
|
|
|
</orderedlist>
|
|
|
|
<para>These recommendations are similar but
|
|
not identical to the <ulink
|
|
url="http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/LaunchOnDemandDaemons.html#//apple_ref/doc/uid/TP40001762-104738">Apple
|
|
MacOS X Daemon Requirements</ulink>.</para>
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>Socket-Based Activation</title>
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>Bus-Based Activation</title>
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>Path-Based Activation</title>
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>Writing Systemd Unit Files</title>
|
|
|
|
<para>When writing systemd unit files, it is
|
|
recommended to consider the following
|
|
suggestions:</para>
|
|
|
|
<orderedlist>
|
|
<listitem><para>If possible do not use
|
|
the <varname>Type=forking</varname>
|
|
setting in service files. But if you
|
|
do, make sure to set the PID file path
|
|
using <varname>PIDFile=</varname>. See
|
|
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
for details.</para></listitem>
|
|
|
|
<listitem><para>If your daemon
|
|
registers a D-Bus name on the bus,
|
|
make sure to use
|
|
<varname>Type=dbus</varname> if
|
|
possible.</para></listitem>
|
|
|
|
<listitem><para>Make sure to set a
|
|
good human-readable description string
|
|
with
|
|
<varname>Description=</varname>.</para></listitem>
|
|
|
|
<listitem><para>Do not disable
|
|
<varname>DefaultDependencies=</varname>,
|
|
unless you really know what you do and
|
|
your unit is involved in early boot or
|
|
late system shutdown.</para></listitem>
|
|
|
|
<listitem><para>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
|
|
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
|
or names introduced by your own
|
|
package to keep the unit file
|
|
operating
|
|
system-independent.</para></listitem>
|
|
|
|
<listitem><para>Make sure to include
|
|
an <literal>[Install]</literal> section including
|
|
installation information for the unit
|
|
file. See
|
|
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
for details. To activate your service
|
|
on boot make sure to add a
|
|
<varname>WantedBy=multi-user.target</varname>
|
|
or
|
|
<varname>WantedBy=graphical.target</varname> directive.</para></listitem>
|
|
|
|
</orderedlist>
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>Installing Service Files</title>
|
|
|
|
<para>At the build installation time
|
|
(e.g. <command>make install</command> during
|
|
package build) packages are recommended to
|
|
install their systemd unit files in the
|
|
directory returned by <command>pkg-config
|
|
systemd
|
|
--variable=systemdsystemnunitdir</command>
|
|
(for system services),
|
|
resp. <command>pkg-config systemd
|
|
--variable=systemdsessionunitdir</command>
|
|
(for session 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. <command>rpm -i</command>
|
|
by the administrator) symlinks should be
|
|
created in the systemd configuration
|
|
directories via the
|
|
<citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
tool, to activate them automatically on
|
|
boot.</para>
|
|
|
|
<para>Packages using
|
|
<citerefentry><refentrytitle>autoconf</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
are recommended to use a configure script
|
|
excerpt like the following to determine the
|
|
unit installation path during source
|
|
configuration:</para>
|
|
|
|
<programlisting>PKG_PROG_PKG_CONFIG
|
|
AC_ARG_WITH([systemdsystemunitdir],
|
|
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
|
|
[], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
|
|
AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
|
|
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir"])</programlisting>
|
|
|
|
<para>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
|
|
session unit directory is left as excercise to the
|
|
reader.)</para>
|
|
|
|
<para>Additionally, to ensure that
|
|
<command>make distcheck</command> continues to
|
|
work, it is recommended to add the following
|
|
to the top-level <filename>Makefile.am</filename>
|
|
file in
|
|
<citerefentry><refentrytitle>automake</refentrytitle><manvolnum>1</manvolnum></citerefentry>-based
|
|
projects:</para>
|
|
|
|
<programlisting>DISTCHECK_CONFIGURE_FLAGS = \
|
|
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)</programlisting>
|
|
|
|
<para>Finally, unit files should be installed in the system with an automake excerpt like the following:</para>
|
|
|
|
<programlisting>if HAVE_SYSTEMD
|
|
systemdsystemunit_DATA = \
|
|
foobar.socket \
|
|
foobar.service
|
|
endif</programlisting>
|
|
|
|
<para>In the
|
|
<citerefentry><refentrytitle>rpm</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
|
<filename>.spec</filename> file use a snippet like
|
|
the following to enable/disable the service
|
|
during installation/deinstallation. Consult
|
|
the packaging guidelines of your distribution
|
|
for details and the equivalent for other
|
|
packaging managers:</para>
|
|
|
|
<programlisting>%post
|
|
/usr/bin/systemd-install enable foobar.service foobar.socket >/dev/null 2>&1 || :
|
|
|
|
%preun
|
|
if [ "$1" -eq 0 ]; then
|
|
/usr/bin/systemd-install disable foobar.service foobar.socket >/dev/null 2>&1 || :
|
|
fi</programlisting>
|
|
|
|
</refsect2>
|
|
|
|
<refsect2>
|
|
<title>Porting Existing Daemons</title>
|
|
|
|
<para>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 this offers additional
|
|
functionality to the daemons as well as it
|
|
simplifies integration into new-style init
|
|
systems.</para>
|
|
|
|
<para>To port an existing SysV compatible
|
|
daemon the following steps are
|
|
recommended:</para>
|
|
|
|
<orderedlist>
|
|
<listitem><para>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.</para></listitem>
|
|
|
|
<listitem><para>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
|
|
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
is checked for already passed sockets
|
|
first. If sockets are passed
|
|
(i.e. when
|
|
<function>sd_listen_fds()</function>
|
|
returns a positive value), skip the
|
|
socket createn 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
|
|
file descriptors are
|
|
passed.</para></listitem>
|
|
|
|
<listitem><para>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.</para></listitem>
|
|
|
|
<listitem><para>If the daemon exposes
|
|
interfaces via D-Bus, write and
|
|
install a D-Bus activation file for
|
|
the service, see above for
|
|
details.</para></listitem>
|
|
</orderedlist>
|
|
|
|
</refsect2>
|
|
|
|
</refsect1>
|
|
|
|
|
|
<refsect1>
|
|
<title>See Also</title>
|
|
<para>
|
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
|
<citerefentry><refentrytitle>systemd-install</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
|
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
|
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
|
<citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
|
</para>
|
|
</refsect1>
|
|
|
|
</refentry>
|