User Tools

Site Tools


docs:guide-developer:procd-init-scripts

procd init script parameters

A procd init script is similiar to an old init script, but with a few differences:

  • procd expects services to run in the foreground
  • Different shebang line: #!/bin/sh /etc/rc.common
  • Explicitly use procd USE_PROCD=1

Example:

#!/bin/sh /etc/rc.common

USE_PROCD=1

To start a service we need the function 'start_service'. stop_service is only needed when you need special things to stop your service. stop_service() is called after procd killed the service. The service itself should run in the foreground. (Apparently

start_service() {
  procd_open_instance [instance_name]
  procd_set_param command /sbin/your_service_daemon -b -a --foo
  procd_append_param command -bar 42 # append command parameters

  # respawn automatically if something died, be careful if you have an alternative process supervisor
  # if process dies sooner than respawn_threshold, it is considered crashed and after 5 retries the service is stopped
  procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}

  procd_set_param env SOME_VARIABLE=funtimes  # pass environment variables to your process
  procd_set_param limits core="unlimited"  # If you need to set ulimit for your process
  procd_set_param file /var/etc/your_service.conf # /etc/init.d/your_service reload will restart the daemon if these files have changed
  procd_set_param netdev dev # likewise, except if dev's ifindex changes.
  procd_set_param data name=value ... # likewise, except if this data changes.
  procd_set_param stdout 1 # forward stdout of the command to logd
  procd_set_param stderr 1 # same for stderr
  procd_set_param user nobody # run service as user nobody
  procd_set_param pidfile /var/run/somefile.pid # write a pid file on instance start and remove it on stop
  procd_close_instance
}

WARNING: initscripts will run while building OpenWRT images (when installing packages in what will become a ROM image) in the host system (right now, for actions “enable” and “disable”). They must not fail, or have undesired side-effects in that situation. When being run by the build system, environment variable ${IPKG_INSTROOT} will be set to the working directory being used. On the “target system”, that environment variable will be empty/unset. Refer to “/lib/functions.sh” and also to “/etc/rc.common” in package “base-files” for the nasty details.

TODO: Table old openwrt initscript ↔ new procd

FIXME For as much information as is available, see the documentation at the top of procd.sh (“See the source” is not documentation.)

Procd triggers on config file / network interface changes

In older versions of OpenWrt, a system called “ucitrack” attempted to track UCI config files, and the processes that depended on each of them, and would restart them all as needed. This too, is replaced with ubus/procd, and expanded to allow notifying services when network interfaces change. This is useful for services like dnsmasq, and proxy/routing software that cares about which network interfaces are in use, and with what configuration.

First, to simply make your service depend on a config file, add a “service_triggers()” clause to your init script

service_triggers()
{
        procd_add_reload_trigger "uci-file-name"
}

This will setup hooks such that issuing 'reload_config' will issue a call to '/etc/init.d/<yourinitscript> reload' when the md5sums of '/etc/config/uci-file-name' has changed. You can edit as many config files as you like, and then issue reload_config, procd will take care of reloading all of them. Note, no change in the config file, no reload. If you want to explicitly reload, you still need to issue '/etc/init.d/<yourservice> reload' manually.

By default, “reload” will cause a stop/start call, _only_ if the md5sum of the final computed command line has changed. (This is in addition to any reload triggers) If your application doesn't use args, but has a generated config file, or parses the uci config file directly, you should add that to procd via 'procd_set_param file /var/etc/your_service.conf' or 'procd_set_param file /etc/config/yourapp' If you don't have any files or args, but still need to explicitly restart when reload is called, you can hook reload_service as shown below. Note that if your file is not in /etc/config, that 'reload_config' won't work, but '/etc/init.d/<service> reload' will still do the right thing.

reload_service()
{
        echo "Explicitly restarting service, are you sure you need this?"
        stop
        start
}

If you want/need your service to depend on changes to networking, simply modify your service_triggers section, like so..

service_triggers()
{
        procd_add_reload_trigger "uci-file-name" "second-uci-file"
        procd_add_interface_trigger "interface.*" <interface> /etc/init.d/<service> reload
}

See use cases of procd_add_interface_trigger and procd_add_reload_trigger in the OpenWrt packages repository.

Signalling a service

Current versions (LEDE 17.01 and up) support sending signals to procd registered services. (OpenWrt-CC gained support for pidfile writing, which allowed third party monitoring services to send signals) This allows, for instance, reload_config and /etc/init.d/yourapp reload to issue a SIGHUP instead of stop/starting your process.

reload_service() {
         procd_send_signal service_name [instance_name] [signal]
}

The signal is SIGHUP by default, and must be specified by NAME. (You can get available signals from kill -l on the console)

The service_name is the basename of the init.d script, eg for /etc/init.d/yourappyourapp.

The instance_name if you wish to signal different instances of your service, comes from the optional parameter to procd_open_instance [instance_name]. If instance_name is unspecified, or '*' then the signal will be delivered to all instances of the service.

Note You can also send signals to named procd services from outside initscripts. Simply load the procd functions and send the signal as before.

#!/bin/sh
. /lib/functions/procd.sh
procd_send_signal service_name [instance_name] [signal]

How do these scripts work?

All arguments are packed into json and send over to procd via ubus

Debugging

Set PROCD_DEBUG=1 to see debugging information when starting or stopping a procd init script. Also, INIT_TRACE=1 /etc/init.d/mything $action Where $action is start/stop etc.

Examples

Service Parameters

The following table contains a listing of the possible values to procd_set_param() and a description of their effects. List values are passed space-separated, e.g. procd_set_param env HOME=/root ENVIRONMENT=production FOO=“bar baz”. String values are implicitely concatenated, so procd_set_param error An error occurred is equivalent to procd_set_param error “An error occurred”.

Parameter Data Type Description
env Key-Value-List Sets a number of environment variables in key=value notation exported to the spawned process.
data Key-Value-List Sets arbitrary user data in key=value notation to the ubus service state. This is mainly used to store additional meta data with spawned services, such as mDNS announcements or firewall rules which may be picked up by other services.
limits Key-Value-List Set ulimit values in key=value notation for the spawned process. The following limit names are recognized by procd: as (RLIMIT_AS), core (RLIMIT_CORE), cpu (RLIMIT_CPU), data (RLIMIT_DATA), fsize (RLIMIT_FSIZE), memlock (RLIMIT_MEMLOCK), nofile (RLIMIT_NOFILE), nproc (RLIMIT_NPROC), rss (RLIMIT_RSS), stack (RLIMIT_STACK), nice (RLIMIT_NICE), rtprio (RLIMIT_RTPRIO), msgqueue (RLIMIT_MSGQUEUE), sigpending (RLIMIT_SIGPENDING)
command List Sets the command vector (argv) used to execute the process.
netdev List Passes a list of Linux network device names to procd to be monitored for changes. Upon starting a service, the interface index of each network device name is resolved and stored as part of procd's in-memory service state. When a service reload request is processed and the interface index of any of the associated network devices changed or if the list itself changed, the running service state is invalidated and procd will restart the associated process or deliver a UNIX signal to it, depending on how the service was set up.
file List Passes a list of file names to procd to be monitored for changes. Upon starting a service, the content of each passed file is checksummed and stored as part of procd's in-memory service state. When a service reload request is processed and the checksum of one of the associated files changed, or the list of files itself changed, the running service state is invalidated and procd will restart the associated process or deliver a UNIX signal to it, depending on how the service was set up.
respawn List A series of three consecutive numbers which set the respawn threshold, the respawn timeout and the respawn retry respectively. The timeout specifies the amount of seconds to wait before a service restart attempt, the retry value controls how many restart attempts will be made before a service is considered crashed and the threshold value in seconds controls the time frame in which the restart attempts are counted towards the retry limit. For example a threshold of 300 with a retry value of 10 will cause procd to consider the service to be crashed if the associated UNIX process terminated more than 10 times within a time frame of 5 minutes. No further restart attempts will be made for such crashed services unless an explicit restart is performed. Setting the retry value to 0 will cause procd to try restarting the service indefinitely. The default value for respawn is 3600 5 5.
watch List Passes a list of ubus namespaces to watch - procd will subcribe to each namespace and wait for incoming ubus events which are then forwarded to registered JSON script triggers for evaluation.
error List Passes one or more free formed error strings to procd. The error strings are stored as part of the in-memory service state and are exposed verbatim in ubus for use by other tools. This facility is mainly useful to allow init scripts to signal configuration errors or other transient issues preventing a successful start up. If any error string is passed to procd, no attempt will be made to actually spawn the associated UNIX process of the service but the service instance itself is still registered in procd.
nice Integer Set the scheduling priority of the spawned process. Valid values range from -20 (most favorable) to 19 (least favorable).
term_timeout Integer Specifies the amount of seconds to wait for a clean process exit after delivering the TERM signal. If the process fails to completely exit within the specified time frame, the process is forcibly terminated using an uncatchable KILL signal. The default termination timeout value is 5 seconds. Services with expensive shutdown operations, such as database systems, should set the term_timeout parameter to sufficiently large value.
reload_signal String Instructs procd to handle process reloads by delivering a UNIX signal instead of terminating the running process and spawning it again. This is useful for programs that provide extensive native configuration reload handling which allows for updated configurations to be applied on the fly without the need to restart the process. Note that this parameter only makes sense in conjunction with fixed command lines. When a reload signal is specified, any updated command line will be ignored since the running process is retained and not executed again. Valid values for this parameter are UNIX signal names as listed by kill -l.
pidfile String Instructs procd to write the PID of the spawned process into the specified file path. While procd itself does not use or require PID files to track spawned processes, this option is useful for sitation where knowledge of the PID is required, e.g. for monitoring or control client software.
user String Specifies the name of the user to spawn the process as. procd will look up the given name in /etc/passwd and set the effective uid and primary gid of the spawned processaccordingly. If omitted, the process is spawned as root (uid 0, gid 0)
seccomp String Specifies the seccomp list for ujail (ujail -S)
capabilities String This parameter is currently unused.
stdout Boolean If set to 1, instruct procd to relay the spawned process' stdout to the system log. The stdout will be fed line-wise to syslog(3) using the basename of the first command argument as identity, LOG_INFO as priority and LOG_DAEMON as facility.
stderr Boolean If set to 1, instruct procd to relay the spawned process' stderr to the system log. The stderr will be fed line-wise to syslog(3) using the basename of the first command argument as identity, LOG_ERR as priority and LOG_DAEMON as facility.
no_new_privs Boolean Instructs ujail to not allow privilege elevation. Sets the ujail -c parameter when true.
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
docs/guide-developer/procd-init-scripts.txt · Last modified: 2019/09/02 17:47 by tmomas