Openrc

From Funtoo
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Service script

Mini howto

Let's start to write our openrc service script(/etc/init.d/mydaemon). The first line is:

#!/sbin/openrc-run

If we use another interpreter, then we may have troubles. Next we add command variable with our binary full path and the file is as follows:

#!/sbin/openrc-run

command="/usr/sbin/mydaemon"

That's all. Now our binary specified in command variable can be started with help of start-stop-daemon.

Next add description variable to supply a user some info about the service:

description="super essential service"

And /etc/init.d/mydaemon describe now shows us:

 * super essential service
 * healthcheck: no description
 * unhealthy: no description
 * cgroup_cleanup: Kill all processes in the cgroup

Great. If our service create a pid file, then we should specify it full path with pidfile variable:

pidfile="/var/run/mydaemon.pid"

This helps start-stop-daemon to detect an already running instance of mydaemon. Next add additional arguments for our daemon with help of command_args variable:

command_args="-c /etc/mydaemon.conf"

If we have special arguments to place the our daemon into the background(and/or force pidfile creation), then we should place it in command_args_background variable.

Next we can tell start-stop-daemon to launch our daemon as an unprivileged user/group with:

command_user="user:group"

Next add dependencies to our service script:

depend() {
  need localmount
  use logger
}

If we need more services, for example, with need keyword, we can use several lines:

need localmount
need net

or place they separated with spaces on a single line:

need localmount net

Where we can use the next keywords with service names separated with spaces:

  • need - a hard dependency - localmount always needs to be started before this service does(if this service is restarted, then our service will be restarted too);
  • use - a soft dependency - if logger is in this runlevel start it before, but we don't care if it's not in this runlevel;
  • want - between need and use - try to start specified services if they are installed on the system, regardless of whether they are in the runlevel, but we don't care if they don't exist;
  • before - our service need to be started before another services(if this service isn't exist or is placed to other runlevel, this settings has no effect);
  • after - our service need to be started after another services(if this service isn't exist or is placed to other runlevel, this settings has no effect);
  • provide - allows multiple implementations to provide one service type(e.g. "provide logger" - thus, any syslogd implementation satisties logger dependency);
  • keyword - platform-specific overrides; see openrc docs for details.

Next add checking of a config file before daemon start:

checkconfig() {
  ...
}
start_pre() {
  checkconfig || return $?
}

Also, we should check a config file on restart to prevent of restarting a running service with a broken config:

start_pre() {
  # Prevent of double check
  if [ "${RC_CMD}" != "restart" ] ; then
    checkconfig || return $?
  fi
}
stop_pre() {
  if [ "${RC_CMD}" = "restart" ] ; then
    checkconfig || return $?
  fi
}

We done this check with help of start_pre()/stop_pre() because openrc convert restart action to a sequence of stop-start actions.

The complete service script is:

#!/sbin/openrc-run

command="/usr/sbin/mydaemon"
command_args="-c /etc/mydaemon.conf"
command_user="user:group"
description="super essential service"
pidfile="/var/run/mydaemon.pid"

depend() {
  need localmount
  use logger
}

checkconfig() {
  ...
}

start_pre() {
  # Prevent of double check
  if [ "${RC_CMD}" != "restart" ] ; then
    checkconfig || return $?
  fi
}

stop_pre() {
  if [ "${RC_CMD}" = "restart" ] ; then
    checkconfig || return $?
  fi
}

Extra commands

To add additional commands we must tell openrc about it and define a function with such name:

extra_commands="cmd1"
description_cmd1="do some additional action"
cmd1() {
  ...
}

Debug mode

To turn on a debug output of a service script set RC_DEBUG variable like this:

~# RC_DEBUG=yes /etc/init.d/ourdaemon start

This makes "set -x" for us.

Variables reference

We set for openrc

  • command="PATH_TO_BIN" - a full path to binary we want to start/stop.
  • command_args="COMMAND LINE ARGUMENTS" - command line arguments for our daemon.
  • command_args_background="COMMAND LINE ARGUMENTS" - command line arguments for our daemon to background itself and/or to create a pid file.
  • command_background=true - tell start-stop-daemon to create a pid file and force a daemon into the background(if daemon can't do it itself).
  • command_user="USER:GROUP" - tell start-stop-daemon to launch our daemon as specified user and group(:GROUP can be ommited).
  • description="DESC TEXT" - a text which is outputed on /etc/init.d/SCRIPT describe command.
  • description_CMD="CMD DESC TEXT" - a text which is outputed on /etc/init.d/SCRIPT describe command as CMD extra command description.
  • directory="PATH" - a value is passed to start-stop-daemon --chdir option.
  • extra_commands="cmd1 cmd2 ..." - add specified additional actions to a service script.
  • extra_started_commands="cmd1 cmd2 ..." - add specified additional actions to a service script, which are only valid while a daemon is running(started).
  • extra_stopped_commands="cmd1 cmd2 ..." - add specified additional actions to a service script, which are only valid while a daemon is not running(stopped).
  • name="SERVICE_NAME" - a service name used in messages that openrc output. By default equal to RC_SVCNAME.
  • pidfile="PATH_TO_PID" - a full path to a pid file created by our daemon or start-stop-daemon(see command_background).
  • start_stop_daemon_args="EXTRA ARGS" - pass extra arguments to start-stop-daemon.

Openrc set for us

  • RC_CMD - a command/action name(e.g. start/stop/restart/status/etc).
  • RC_RUNLEVEL - a current runlevel.
  • RC_SVCNAME - a service script name(e.g. mydaemon.local).
  • RC_SERVICE - a service script full path(e.g. /etc/init.d/mydaemon.local).

Function reference

We set for openrc

  • depend() - declare dependencies of a service
  • start_pre() - actions to do before a service start
  • start() - actions to start a service
  • start_post() - actions to do after a service start
  • stop_pre() - actions to do before a service stop
  • stop() - actions to stop a service
  • stop_post() - actions to do after a service stop

Openrc set for us

  • ebegin "MSG" - output an action message.
  • eend EXIT_CODE - output an action status (0 exit code is interpreted as success, !0 - as fail); a companion of ebegin.
  • eerror "MSG" - output error message
  • eerrorn "MSG" - output error message without newline at the end
  • einfo "MSG" - output info message
  • einfon "MSG" - output info message without newline at the end
  • ewarn "MSG" - output warning message
  • ewarnn "MSG" - output warning message without newline at the end

References

You can get more info about openrc internals from:

  • /usr/share/doc/openrc-*/*
  • /lib/rc/sh/openrc-run.sh
  • /lib/rc/sh/start-stop-daemon.sh
  • /lib/rc/sh/*