Openrc

From Funtoo
Jump to: navigation, search

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/*