docs/manual/adding-packages-directory: describe start script details

This codifies style elements discussed on the mailing list, most
importantly PID file handling, and adds detailed considerations for
writing start scripts.

References:
https://lore.kernel.org/buildroot/20240712124956.3925574-1-fiona.klute@gmx.de/
https://lore.kernel.org/buildroot/20240714223645.39adf8c6@windsurf/
https://lore.kernel.org/buildroot/9ec13ac0-b5b6-4251-98b8-0d8f7adac452@gmx.de/

Signed-off-by: Fiona Klute (WIWA) <fiona.klute@gmx.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
This commit is contained in:
Fiona Klute (WIWA) 2024-10-28 18:29:43 +01:00 committed by Thomas Petazzoni
parent c808e271e3
commit 67249a691d

View File

@ -576,23 +576,120 @@ name. The +NN+ is the start order number which needs to be carefully
chosen. For example, a program that requires networking to be up should
not start before +S40network+. The scripts are started in alphabetical
order, so +S01syslogd+ starts before +S01watchdogd+, and +S02sysctl+
start thereafter.
starts thereafter.
[source,sh]
----
include::S01syslogd[]
----
*Note:* programs that support reloading their configuration in some
fashion (+SIGHUP+) should provide a +reload()+ function similar to
+stop()+. The +start-stop-daemon+ command supports +--stop --signal
HUP+ for this. It is recommended to always append +--exec
"/sbin/$DAEMON"+ to all +start-stop-daemon+ commands to ensure signals
are set to a PID that matches +$DAEMON+.
Scripts should use long form options where possible for clarity.
Both start scripts and unit files can source command line arguments from
+/etc/default/foo+, in general, if such a file does not exist it should
not block the start of the daemon, unless there is some site specirfic
command line argument the daemon requires to start. For start scripts a
+FOO_ARGS="-s -o -m -e -args"+ can be defined to a default value in and
the user can override this from +/etc/default/foo+.
==== Start script configuration
Both start scripts and unit files can source command line arguments
from +/etc/default/foo+, where +foo+ is the daemon name as set in the
+DAEMON+ variable. In general, if such a file does not exist it should
not block the start of the daemon, unless there is some site specific
command line argument the daemon requires to start. For start scripts
+FOO_ARGS="-s -o -m -e -args"+ can be defined to a default value in
the script, and the user can override this from +/etc/default/foo+.
==== Handling the PID file
A PID file is needed to keep track of what the main process of a
service is. How to handle it depends on whether the service creates
its own PID file, and if it deletes it on shutdown.
* If your service doesn't create its own PID file, invoke the daemon
in foreground mode, and use +start-stop-daemon --make-pidfile
--background+ to let +start-stop-daemon+ create the PID file. See
+S01syslogd+ for example:
+
[source,sh]
----
start-stop-daemon --start --background --make-pidfile \
--pidfile "$PIDFILE" --exec "/sbin/$DAEMON" \
-- -n $SYSLOGD_ARGS
----
* If your service creates its own PID file, pass the +--pidfile+
option to both +start-stop-daemon+ *and the daemon itself* (or set
it appropriately in a configuration file, depending on what the
daemon supports) so they agree on where the PID file is. See
+S45NetworkManager+ for example:
+
[source,sh]
----
start-stop-daemon --start --pidfile "$PIDFILE" \
--exec "/usr/sbin/$DAEMON" \
-- --pid-file="$PIDFILE" $NETWORKMANAGER_ARGS
----
* If your service removes its PID file on shutdown, use a loop testing
that the PID file has disappeared on stop, see +S45NetworkManager+
for example:
+
[source,sh]
----
while [ -f "$PIDFILE" ]; do
sleep 0.1
done
----
* If your service doesn't remove its PID file on shutdown, use a loop
with +start-stop-daemon+ checking if the service is still running,
and delete the PID file after the process is gone. See +S01syslogd+
for example:
+
[source,sh]
----
while start-stop-daemon --stop --test --quiet --pidfile "$PIDFILE" \
--exec "/sbin/$DAEMON"; do
sleep 0.1
done
rm -f "$PIDFILE"
----
+
Note the +--test+ flag, which tells +start-stop-daemon+ to not
actually stop the service, but test if it would be possible to, which
fails if the service is not running.
==== Stopping the service
The stop function should check that the daemon process is actually
gone before returning, otherwise restart might fail because the new
instance is started before the old one has actually stopped. How to do
that depends on how the PID file for the service is handled (see
above). It is recommended to always append +--exec "/sbin/$DAEMON"+ to
all +start-stop-daemon+ commands to ensure signals are sent to a PID
that matches +$DAEMON+.
==== Reloading service configuration
Programs that support reloading their configuration in some fashion
(e.g. +SIGHUP+) should provide a +reload()+ function similar to
+stop()+. The +start-stop-daemon+ command supports +--stop --signal
HUP+ for this. When sending signals this way, whether SIGHUP or
others, make sure to use the symbolic names and not signal
numbers. Signal numbers can vary between CPU architectures, and names
are also easier to read.
==== Return codes
The action functions of the start script should return a success (or
failure) code, usually the return code of the relevant
start-stop-daemon action. The last one of those should be the return
code of the start script as a whole, to allow automatically checking
for success, e.g. when calling the start script from other
scripts. Note that without an explicit +return+ the return code of the
last command in a script or function becomes its return code, so an
explicit return is not always necessary.
==== Logging
When a service forks to the background, or +start-stop-daemon
--background+ does that, stdout and stderr are generally closed, and
anything log messages the service may write there get lost. If
possible, configure your service to log to syslog (preferably), or a
dedicated log file.