git: e9bc86f962 - main - rc scripting article: file naming convention and "instancing"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 16 Jul 2024 10:10:32 UTC
The branch main has been updated by netchild: URL: https://cgit.FreeBSD.org/doc/commit/?id=e9bc86f962c2f68329211cd7e27738066f399a69 commit e9bc86f962c2f68329211cd7e27738066f399a69 Author: Alexander Leidinger <netchild@FreeBSD.org> AuthorDate: 2024-07-16 10:07:03 +0000 Commit: Alexander Leidinger <netchild@FreeBSD.org> CommitDate: 2024-07-16 10:10:29 +0000 rc scripting article: file naming convention and "instancing" - emphasize the file naming convention and why - add a section about "instancing" Reviewed by: Pau Amma (doc/english bits) Differential Revision: https://reviews.freebsd.org/D45897 --- .../content/en/articles/rc-scripting/_index.adoc | 105 ++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/documentation/content/en/articles/rc-scripting/_index.adoc b/documentation/content/en/articles/rc-scripting/_index.adoc index 6511be73a4..21a7eb4d68 100644 --- a/documentation/content/en/articles/rc-scripting/_index.adoc +++ b/documentation/content/en/articles/rc-scripting/_index.adoc @@ -185,7 +185,9 @@ That is, each [.filename]#rc.d# script _must_ set `name` before it calls man:rc. Now it is the right time to choose a unique name for our script once and for all. We will use it in a number of places while developing the script. -For a start, let us give the same name to the script file, too. +The content of the name variable needs to match the script name, +some parts of FreeBSD (e.g. <<rcng-service-jails, service jails>> and the cpuset feature of the rc framework) depend upon this. +As such the filename shall also not contain characters which may be troublesome in scripting (e.g. do not use a hyphen "-" and others). [NOTE] ==== @@ -906,6 +908,107 @@ run_rc_command "$1" ➊ The disabling needs to happen after the ``load_rc_config`` call, else a man:rc.conf[5] setting may override it. +[[rcng-instancing]] +== Advanced rc-scripting: Instancing + +Sometimes it is useful to run several instances of a service. +Typically you want ot be able to start/stop such instances independently, +and you want to have a separate config file for each instance. +Each instance should be started at boot, +survive updates, +and benefit from updates. + +Here is an example of a rc script which supports this: + +[.programlisting] +.... +#!/bin/sh + +# +# PROVIDE: dummy +# REQUIRE: NETWORKING SERVERS +# KEYWORD: shutdown +# +# Add these following line to /etc/rc.conf.local or /etc/rc.conf +# to enable this service: +# +# dummy_enable (bool): Set it to YES to enable dummy on startup. +# Default: NO +# dummy_user (string): User account to run with. +# Default: www +# + +. /etc/rc.subr + +case $0 in <.> +/etc/rc*) + # during boot (shutdown) $0 is /etc/rc (/etc/rc.shutdown), + # so get the name of the script from $_file + name=$_file + ;; +*) + name=$0 + ;; +esac + +name=${name##*/} <.> +rcvar="${name}_enable" <.> +desc="Short description of this service" +command="/usr/local/sbin/dummy" + +load_rc_config "$name" + +eval "${rcvar}=\${${rcvar}:-'NO'}" <.> +eval "${name}_svcj_options=\${${name}_svcj_options:-'net_basic'}" <.> +eval "_dummy_user=\${${name}_user:-'www'}" <.> + +_dummy_configname=/usr/local/etc/${name}.cfg <.> +pidfile=/var/run/dummy/${name}.pid +required_files ${_dummy_configname} +command_args="-u ${_dummy_user} -c ${_dummy_configfile} -p ${pidfile}" + +run_rc_command "$1" +.... + +➊ and ➋ make sure to set the name variable to the man:basename[1] of the script name. +If the filename is [.filename]#/usr/local/etc/rc.d/dummy#, +name is set to [.filename]#dummy#. +This way changing the filename of the rc script changes automatically the content of the name variable. + +➌ specifies the variable name which is used in [.filename]#rc.conf# to enable this service based upon the filename of this script. +In this example this resolves to dummy_enable. + +➍ makes sure the default for the _enable variable is NO. + +➎ is an example of having some defaults for service specific framework variables, +in this case the service jails options. + +➏ and ➐ set variables internal to the script (pay attention to the underscore in front of _dummy_user to make it different from dummy_user which can be set in [.filename]#rc.conf#). + +The part in ➎ is for variables which are not used inside the script itself but in the rc framework. +All the variables which are used as parameters somewhere in the script are assigned to a generic variable like in ➐ to make it more easy to reference them (no need to eval them at each place of use). + +This script will now behave differently if the start script has a different name. +This allows to creaty symlinks to it: + +[source,shell] +.... +# ln -s dummy /usr/local/etc/rc.d/dummy_foo +# sysrc dummy_foo_enable=YES +# service dummy_foo start +.... + +The above creates an instance of the dummy service with the name dummy_foo. +It does not use the config file [.filename]#/usr/local/etc/dummy.cfg# but the config file [.filename]#/usr/local/etc/dummy_foo.cfg# (➐), +and it uses the PID file [.filename]#/var/run/dummy/dummy_foo.pid# instead of [.filename]#/var/run/dummy/dummy.pid#. + +The services dummy and dummy_foo can be managend indepently of each other, +while having the start script update itself on package update (due to the symlink). +This does not update the REQUIRE line, +as such there is no easy way of depending on a specific instance. +To depend upon a specific instance in the startup order a copy needs to be made instead of using a symlink. +This prevents the automatic pick-up of changes to the start script when an update is installed. + [[rcng-furthur]] == Further reading