]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
man/systemd.service: advise Type=exec instead of Type=simple 28596/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 30 Jul 2023 10:11:33 +0000 (12:11 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 31 Jul 2023 09:23:36 +0000 (11:23 +0200)
The descriptions of various options are reworked: first say what protocol
actually is, i.e. describe what type of notification the manager waits
for. Only after that describe various steps and things the service should
do. Also, apply some paragraph breaks.

Instead of recommending Type=simple, recommend Type=exec. Say explicitly that
Type=simple, Type=forking are not recommended. Type=simple ignores failure in a
way that doesn't make any sense except as a historical accident. We introduced
'exec' instead of changing 'simple' to keep backwards-compatiblity, but
'simple' is not very useful. 'forking' works, but is inefficient: correctly
programming the interface requires a lot of work, and at runtime, the
additional one or two forks are just a waste of CPU resources. Furthermore, we
now understand that because of COW traps, they may also increase memory
requirements. There is really no reason to use 'forking', except if it's
already implemented and the code cannot be changed to use 'notify'.

Also, remove the recommendations to use Type=simple to avoid delaying boot. In
most cases, if the service can support notifications about startup, those
should be done.

Overall, for new services, "notify", "notify-reload", and "dbus" are the
types that make sense.

man/systemd.service.xml

index 6237d27f00c0b05a5de6c6617a6ddb9351d7bf9a..b09cdd4ecf551f6341f74f6c9c06fcb899f7dd0b 100644 (file)
         <term><varname>Type=</varname></term>
 
         <listitem>
-          <para>Configures the process start-up type for this service unit. One of <option>simple</option>,
-          <option>exec</option>, <option>forking</option>, <option>oneshot</option>, <option>dbus</option>,
-          <option>notify</option>, <option>notify-reload</option> or <option>idle</option>:</para>
+          <para>Configures the mechanism via which the service notifies the manager that the service start-up
+          has finished. One of <option>simple</option>, <option>exec</option>, <option>forking</option>,
+          <option>oneshot</option>, <option>dbus</option>, <option>notify</option>,
+          <option>notify-reload</option>, or <option>idle</option>:</para>
 
           <itemizedlist>
             <listitem><para>If set to <option>simple</option> (the default if <varname>ExecStart=</varname> is
             specified but neither <varname>Type=</varname> nor <varname>BusName=</varname> are), the service manager
-            will consider the unit started immediately after the main service process has been forked off. It is
-            expected that the process configured with <varname>ExecStart=</varname> is the main process of the
-            service. In this mode, if the process offers functionality to other processes on the system, its
-            communication channels should be installed before the service is started up (e.g.  sockets set up by
-            systemd, via socket activation), as the service manager will immediately proceed starting follow-up units,
-            right after creating the main service process, and before executing the service's binary. Note that this
-            means <command>systemctl start</command> command lines for <option>simple</option> services will report
-            success even if the service's binary cannot be invoked successfully (for example because the selected
-            <varname>User=</varname> doesn't exist, or the service binary is missing).</para></listitem>
-
-            <listitem><para>The <option>exec</option> type is similar to <option>simple</option>, but the service
-            manager will consider the unit started immediately after the main service binary has been executed. The service
-            manager will delay starting of follow-up units until that point. (Or in other words:
-            <option>simple</option> proceeds with further jobs right after <function>fork()</function> returns, while
-            <option>exec</option> will not proceed before both <function>fork()</function> and
-            <function>execve()</function> in the service process succeeded.) Note that this means <command>systemctl
-            start</command> command lines for <option>exec</option> services will report failure when the service's
-            binary cannot be invoked successfully (for example because the selected <varname>User=</varname> doesn't
+            will consider the unit started immediately after the main service process has been forked off.
+            <emphasis>The use of this type is discouraged, use <option>exec</option> instead.
+            </emphasis></para>
+
+            <para>It is expected that the process configured with <varname>ExecStart=</varname> is the main
+            process of the service. In this mode, if the process offers functionality to other processes on
+            the system, its communication channels should be installed before the service is started up
+            (e.g. sockets set up by systemd, via socket activation), as the service manager will immediately
+            proceed starting follow-up units, right after creating the main service process, and before
+            executing the service's binary. Note that this means <command>systemctl start</command> command
+            lines for <option>simple</option> services will report success even if the service's binary
+            cannot be invoked successfully (for example because the selected <varname>User=</varname> doesn't
             exist, or the service binary is missing).</para></listitem>
 
-            <listitem><para>If set to <option>forking</option>, it is expected that the process configured with
-            <varname>ExecStart=</varname> will call <function>fork()</function> as part of its start-up. The parent
-            process is expected to exit when start-up is complete and all communication channels are set up. The child
-            continues to run as the main service process, and the service manager will consider the unit started when
-            the parent process exits. This is the behavior of traditional UNIX services. If this setting is used, it is
-            recommended to also use the <varname>PIDFile=</varname> option, so that systemd can reliably identify the
-            main process of the service. systemd will proceed with starting follow-up units as soon as the parent
-            process exits.</para></listitem>
+            <listitem><para>The <option>exec</option> type is similar to <option>simple</option>, but the
+            service manager will consider the unit started immediately after the main service binary has been
+            executed. The service manager will delay starting of follow-up units until that point. (Or in
+            other words: <option>simple</option> proceeds with further jobs right after
+            <function>fork()</function> returns, while <option>exec</option> will not proceed before both
+            <function>fork()</function> and <function>execve()</function> in the service process succeeded.)
+            Note that this means <command>systemctl start</command> command lines for <option>exec</option>
+            services will report failure when the service's binary cannot be invoked successfully (for
+            example because the selected <varname>User=</varname> doesn't exist, or the service binary is
+            missing).</para></listitem>
+
+            <listitem><para>If set to <option>forking</option>, the manager will consider the unit started
+            immediately after the binary that forked off by the manager exits. <emphasis>The use of this type
+            is discouraged, use <option>notify</option>, <option>notify-reload</option>, or
+            <option>dbus</option> instead.</emphasis></para>
+
+            <para>It is expected that the process configured with <varname>ExecStart=</varname> will call
+            <function>fork()</function> as part of its start-up. The parent process is expected to exit when
+            start-up is complete and all communication channels are set up. The child continues to run as the
+            main service process, and the service manager will consider the unit started when the parent
+            process exits. This is the behavior of traditional UNIX services. If this setting is used, it is
+            recommended to also use the <varname>PIDFile=</varname> option, so that systemd can reliably
+            identify the main process of the service. The manager will proceed with starting follow-up units
+            after the parent process exits.</para></listitem>
 
             <listitem><para>Behavior of <option>oneshot</option> is similar to <option>simple</option>;
             however, the service manager will consider the unit up after the main process exits. It will then
             of service. <varname>Type=</varname><option>oneshot</option> is the implied default if neither
             <varname>Type=</varname> nor <varname>ExecStart=</varname> are specified. Note that if this
             option is used without <varname>RemainAfterExit=</varname> the service will never enter
-            <literal>active</literal> unit state, but directly transition from <literal>activating</literal>
-            to <literal>deactivating</literal> or <literal>dead</literal> since no process is configured that
-            shall run continuously. In particular this means that after a service of this type ran (and which
-            has <varname>RemainAfterExit=</varname> not set) it will not show up as started afterwards, but
-            as dead.</para></listitem>
+            <literal>active</literal> unit state, but will directly transition from
+            <literal>activating</literal> to <literal>deactivating</literal> or <literal>dead</literal>,
+            since no process is configured that shall run continuously. In particular this means that after a
+            service of this type ran (and which has <varname>RemainAfterExit=</varname> not set) it will not
+            show up as started afterwards, but as dead.</para></listitem>
 
             <listitem><para>Behavior of <option>dbus</option> is similar to <option>simple</option>; however,
-            it is expected that the service acquires a name on the D-Bus bus, as configured by
-            <varname>BusName=</varname>. systemd will proceed with starting follow-up units after the D-Bus
-            bus name has been acquired. Service units with this option configured implicitly gain
-            dependencies on the <filename>dbus.socket</filename> unit. This type is the default if
-            <varname>BusName=</varname> is specified. A service unit of this type is considered to be in the
+            units of this type must have the <varname>BusName=</varname> specified and the service manager
+            will consider the unit up when the specified bus name has been acquired. This type is the default
+            if <varname>BusName=</varname> is specified.</para>
+
+            <para>Service units with this option configured implicitly gain dependencies on the
+            <filename>dbus.socket</filename> unit. A service unit of this type is considered to be in the
             activating state until the specified bus name is acquired. It is considered activated while the
             bus name is taken. Once the bus name is released the service is considered being no longer
             functional which has the effect that the service manager attempts to terminate any remaining
             units after this notification message has been sent. If this option is used,
             <varname>NotifyAccess=</varname> (see below) should be set to open access to the notification
             socket provided by systemd. If <varname>NotifyAccess=</varname> is missing or set to
-            <option>none</option>, it will be forcibly set to <option>main</option>.</para></listitem>
-
-            <listitem><para>Behavior of <option>notify-reload</option> is identical to
-            <option>notify</option>. However, it extends the logic in one way: the
-            <constant>SIGHUP</constant> UNIX process signal is sent to the service's main process when the
-            service is asked to reload. (The signal to send can be tweaked via
-            <varname>ReloadSignal=</varname>, see below.)  When
-            initiating the reload process the service is then expected to reply with a notification message
-            via <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+            <option>none</option>, it will be forcibly set to <option>main</option>.</para>
+
+            <para>If the service supports reloading, and uses the a signal to start the reload, using
+            <option>notify-reload</option> instead is recommended.</para></listitem>
+
+            <listitem><para>Behavior of <option>notify-reload</option> is similar to <option>notify</option>,
+            with one difference: the <constant>SIGHUP</constant> UNIX process signal is sent to the service's
+            main process when the service is asked to reload and the manager will wait for a notification
+            about the reload being finished.</para>
+
+            <para>When initiating the reload process the service is expected to reply with a notification
+            message via
+            <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
             that contains the <literal>RELOADING=1</literal> field in combination with
             <literal>MONOTONIC_USEC=</literal> set to the current monotonic time
             (i.e. <constant>CLOCK_MONOTONIC</constant> in
             in μs, formatted as decimal string. Once reloading is complete another notification message must
             be sent, containing <literal>READY=1</literal>. Using this service type and implementing this
             reload protocol is an efficient alternative to providing an <varname>ExecReload=</varname>
-            command for reloading of the service's configuration.</para></listitem>
+            command for reloading of the service's configuration.</para>
+
+            <para>The signal to send can be tweaked via <varname>ReloadSignal=</varname>, see below.</para>
+            </listitem>
 
             <listitem><para>Behavior of <option>idle</option> is very similar to <option>simple</option>; however,
             actual execution of the service program is delayed until all active jobs are dispatched. This may be used
             anyway.</para></listitem>
           </itemizedlist>
 
-          <para>It is generally recommended to use <varname>Type=</varname><option>simple</option> for
+          <para>It is generally recommended to use <varname>Type=</varname><option>exec</option> for
           long-running services whenever possible, as it is the simplest and fastest option. However, as this
           service type won't propagate service start-up failures and doesn't allow ordering of other units
           against completion of initialization of the service (which for example is useful if clients need to
           connect to the service through some form of IPC, and the IPC channel is only established by the
           service itself — in contrast to doing this ahead of time through socket or bus activation or
           similar), it might not be sufficient for many cases. If so, <option>notify</option>,
-          <option>notify-reload</option> or <option>dbus</option> (the latter only in case the service
+          <option>notify-reload</option>, or <option>dbus</option> (the latter only in case the service
           provides a D-Bus interface) are the preferred options as they allow service program code to
           precisely schedule when to consider the service started up successfully and when to proceed with
           follow-up units. The <option>notify</option>/<option>notify-reload</option> service types require
           explicit support in the service codebase (as <function>sd_notify()</function> or an equivalent API
           needs to be invoked by the service at the appropriate time) — if it's not supported, then
-          <option>forking</option> is an alternative: it supports the traditional UNIX service start-up
-          protocol. Finally, <option>exec</option> might be an option for cases where it is enough to ensure
-          the service binary is invoked, and where the service binary itself executes no or little
-          initialization on its own (and its initialization is unlikely to fail). Note that using any type
-          other than <option>simple</option> possibly delays the boot process, as the service manager needs
-          to wait for service initialization to complete. It is hence recommended not to needlessly use any
-          types other than <option>simple</option>. (Also note it is generally not recommended to use
-          <option>idle</option> or <option>oneshot</option> for long-running services.)</para>
+          <option>forking</option> is an alternative: it supports the traditional heavy-weight UNIX service
+          start-up protocol. Note that using any type other than
+          <option>simple</option>/<option>exec</option> possibly delays the boot process, as the service
+          manager needs to wait for service initialization to complete. (Also note it is generally not
+          recommended to use <option>idle</option> or <option>oneshot</option> for long-running services.)
+          </para>
         </listitem>
       </varlistentry>