Writing Init Scripts: Difference between revisions
Clandmeter (talk | contribs) (→Basics) |
(use https) |
||
(29 intermediate revisions by 8 users not shown) | |||
Line 3: | Line 3: | ||
== Introduction == | == Introduction == | ||
Alpine Linux uses the [https://github.com/OpenRC/openrc OpenRC] init system to start services. Don't confuse OpenRC init with | Alpine Linux uses the [https://github.com/OpenRC/openrc OpenRC] init system to start services. Don't confuse OpenRC init with our system init (the first process that is executed aka pid 1). Many of the current init.d script found in Alpine Linux are taken from Gentoo. If you want to save time you could search [https://packages.gentoo.org/categories Gentoo's repository] for an existing initscript for your service. You can also check [https://wiki.gentoo.org/wiki/Handbook:X86/Working/Initscripts#Writing_initscripts Gentoo's wiki] for some additional OpenRC information. | ||
<strong>NOTE</strong>: OpenRC recently added [https://github.com/OpenRC/openrc/blob/master/service-script-guide.md documentation] on how to write proper Init scripts. Make sure you read it! | |||
If you cannot find an init.d script from Gentoo, or you just want to start to write your own init.d scripts, we provide you with some basic information on how to write simple OpenRC init scripts. | If you cannot find an init.d script from Gentoo, or you just want to start to write your own init.d scripts, we provide you with some basic information on how to write simple OpenRC init scripts. | ||
Primary information about the OpenRC format can be found in the [ | Primary information about the OpenRC format can be found in the [https://manpages.org/openrc-run/8 OpenRC man page openrc-run]. | ||
<pre> | |||
apk add openrc-doc | |||
man openrc-run | |||
</pre> | |||
== Things to avoid == | |||
* Do '''not''' define <code>supervisor=supervise-daemon</code> in init.d script! This way the user cannot disable it without modifying the init.d script. If you really want to predefine ''supervise-daemon'' for particular service, define it in the corresponding conf.d file. | |||
<code> | * Prefer standard OpenRC variables such as <code>command_args</code>, <code>command_user</code> etc. (see [https://www.mankier.com/8/openrc-run openrc-run(8)]); do not create unnecessary config variables like <code>FOO_OPTS</code>, <code>FOO_USER</code> etc. If you want to predefine the default value in init.d script, use common idiom <code>: ${command_user=foo}</code>. | ||
<code> | * Use snake_case for naming extra configuration variables (to be consistent with the OpenRC variables and other init scripts in Alpine). Do not prefix them with the service name, try to be consistent with existing init scripts (e.g. <code>cfgfile</code>, <code>cfgdir</code>, <code>logfile</code>, <code>cachedir</code>, <code>listen_on</code>, <code>start_wait</code>, …). | ||
== | == Minimal Templates == | ||
Every init.d script you write needs to start with a [https://en.wikipedia.org/wiki/Shebang_(Unix) shebang] like: | Every init.d script you write needs to start with a [https://en.wikipedia.org/wiki/Shebang_(Unix) shebang] like: | ||
Line 19: | Line 30: | ||
<code>#!/sbin/openrc-run</code> | <code>#!/sbin/openrc-run</code> | ||
=== Services relying on OpenRC exclusively === | |||
<pre> | |||
#!/sbin/openrc-run | |||
command=/path/to/command | |||
</pre> | |||
=== Services supervised by [https://www.skarnet.org/software/s6/ s6] === | |||
Notes: | |||
* Install and configure the <code>s6-scan</code> service to start on system boot | |||
* Exclude <code>start()</code>, <code>stop()</code> and <code>status()</code> functions in order for s6 supervision to work reliably. OpenRC has built-in equivalent functions which invoke the necessary s6 commands. | |||
* Include a <code>depend()</code> stanza to ensure that the <code>s6-svscan</code> service is already running. | |||
* Add a <code>start_pre()</code> stanza to symlink the service directory into the scan directory, because the <code>/etc/init.d/bootmisc</code> scripts cleans out the <code>/run</code> directory on system boot. | |||
<pre> | |||
#!/sbin/openrc-run | |||
name="foo" | |||
supervisor="s6" | |||
s6_service_path="${RC_SVCDIR}/s6-scan/${name}" | |||
depend() { | |||
need s6-svscan | |||
} | |||
start_pre() { | |||
if [ ! -L "${RC_SVC_DIR}/s6-scan/${name}" ]; then | |||
ln -s "/path/to/${name}/service/dir" "${RC_SVCDIR}/s6-scan/${name}" | |||
fi | |||
} | |||
</pre> | |||
The rest of the below | The rest of the below basic example could be omitted, but that would most probably leave you with an non working initd script. | ||
== Basic example == | == Basic example == | ||
Line 31: | Line 73: | ||
name=$RC_SVCNAME | name=$RC_SVCNAME | ||
cfgfile="/etc/$RC_SVCNAME/$RC_SVCNAME.conf" | |||
command="/usr/bin/my_daemon" | command="/usr/bin/my_daemon" | ||
command_args="--my-daemon-args" | command_args="--my-daemon-args" | ||
command_user="my_system_user" | |||
pidfile="/run/$RC_SVCNAME/$RC_SVCNAME.pid" | pidfile="/run/$RC_SVCNAME/$RC_SVCNAME.pid" | ||
start_stop_daemon_args="--args-for-start-stop-daemon" | start_stop_daemon_args="--args-for-start-stop-daemon" | ||
command_background="yes" | command_background="yes" | ||
Line 48: | Line 91: | ||
</pre> | </pre> | ||
== | == start, stop, restart functions == | ||
OpenRC defined a few basic functions ie: start, stop, restart. These functions are defined by default but can be overwritten by defining your own set of functions. | |||
This is generally only necessary if you want to do something special which is not provided by the default start/stop/restart implementations. | |||
=== start === | |||
<pre> | <pre> | ||
Line 62: | Line 109: | ||
} | } | ||
</pre> | </pre> | ||
=== stop === | |||
=== restart === | |||
== Daemon, Forking, Logging == | |||
TODO... | |||
[[Category:Booting]] | [[Category:Booting]] |
Latest revision as of 21:20, 25 August 2023
This material is work-in-progress ... Do not follow instructions here until this notice is removed. |
Introduction
Alpine Linux uses the OpenRC init system to start services. Don't confuse OpenRC init with our system init (the first process that is executed aka pid 1). Many of the current init.d script found in Alpine Linux are taken from Gentoo. If you want to save time you could search Gentoo's repository for an existing initscript for your service. You can also check Gentoo's wiki for some additional OpenRC information.
NOTE: OpenRC recently added documentation on how to write proper Init scripts. Make sure you read it!
If you cannot find an init.d script from Gentoo, or you just want to start to write your own init.d scripts, we provide you with some basic information on how to write simple OpenRC init scripts.
Primary information about the OpenRC format can be found in the OpenRC man page openrc-run.
apk add openrc-doc man openrc-run
Things to avoid
- Do not define
supervisor=supervise-daemon
in init.d script! This way the user cannot disable it without modifying the init.d script. If you really want to predefine supervise-daemon for particular service, define it in the corresponding conf.d file.
- Prefer standard OpenRC variables such as
command_args
,command_user
etc. (see openrc-run(8)); do not create unnecessary config variables likeFOO_OPTS
,FOO_USER
etc. If you want to predefine the default value in init.d script, use common idiom: ${command_user=foo}
.
- Use snake_case for naming extra configuration variables (to be consistent with the OpenRC variables and other init scripts in Alpine). Do not prefix them with the service name, try to be consistent with existing init scripts (e.g.
cfgfile
,cfgdir
,logfile
,cachedir
,listen_on
,start_wait
, …).
Minimal Templates
Every init.d script you write needs to start with a shebang like:
#!/sbin/openrc-run
Services relying on OpenRC exclusively
#!/sbin/openrc-run command=/path/to/command
Services supervised by s6
Notes:
- Install and configure the
s6-scan
service to start on system boot - Exclude
start()
,stop()
andstatus()
functions in order for s6 supervision to work reliably. OpenRC has built-in equivalent functions which invoke the necessary s6 commands. - Include a
depend()
stanza to ensure that thes6-svscan
service is already running. - Add a
start_pre()
stanza to symlink the service directory into the scan directory, because the/etc/init.d/bootmisc
scripts cleans out the/run
directory on system boot.
#!/sbin/openrc-run name="foo" supervisor="s6" s6_service_path="${RC_SVCDIR}/s6-scan/${name}" depend() { need s6-svscan } start_pre() { if [ ! -L "${RC_SVC_DIR}/s6-scan/${name}" ]; then ln -s "/path/to/${name}/service/dir" "${RC_SVCDIR}/s6-scan/${name}" fi }
The rest of the below basic example could be omitted, but that would most probably leave you with an non working initd script.
Basic example
#!/sbin/openrc-run name=$RC_SVCNAME cfgfile="/etc/$RC_SVCNAME/$RC_SVCNAME.conf" command="/usr/bin/my_daemon" command_args="--my-daemon-args" command_user="my_system_user" pidfile="/run/$RC_SVCNAME/$RC_SVCNAME.pid" start_stop_daemon_args="--args-for-start-stop-daemon" command_background="yes" depend() { need net } start_pre() { checkpath --directory --owner $command_user:$command_user --mode 0775 \ /run/$RC_SVCNAME /var/log/$RC_SVCNAME }
start, stop, restart functions
OpenRC defined a few basic functions ie: start, stop, restart. These functions are defined by default but can be overwritten by defining your own set of functions. This is generally only necessary if you want to do something special which is not provided by the default start/stop/restart implementations.
start
start() { ebegin "Starting mydaemon" start-stop-daemon --start \ --exec /usr/sbin/mydaemon \ --pidfile /var/run/mydaemon.pid \ -- \ --args-for-mydaemon eend $? }
stop
restart
Daemon, Forking, Logging
TODO...