| Both sides previous revision Previous revision Next revision | Previous revision |
| docs:guide-developer:procd-init-scripts [2022/04/12 06:57] – add procd_set_param term_timeout lucize | docs:guide-developer:procd-init-scripts [2024/02/10 16:23] (current) – [Defining service instances] systemcrash |
|---|
| ======procd init script parameters ====== | ====== procd init scripts ====== |
| |
| A procd init script is similiar to an old init script, but with a few differences: | A procd init script is similiar to an old init script, but with a few differences: |
| |
| * procd expects services to **run in the foreground** | * procd expects services to start as if they were to **run in the foreground**, but of course procd runs them the background. |
| * Different shebang line: ''#!/bin/sh /etc/rc.common'' | * Different shebang line: ''#!/bin/sh /etc/rc.common'' |
| * procd expects that shell variable (not environment variable) ''initscript'' is set to the path of the script that invoked it | * procd expects that shell variable (not environment variable) ''initscript'' is set to the path of the script that invoked it |
| |
| Example: | Example: |
| <code> | <code bash> |
| #!/bin/sh /etc/rc.common | #!/bin/sh /etc/rc.common |
| |
| - Settings that ''procd'' should use (e.g. auto respawning, logging stdout, user to use) - optional | - Settings that ''procd'' should use (e.g. auto respawning, logging stdout, user to use) - optional |
| |
| All above information is stored by ''procd'' as a service instance state. On every relevant system change (e.g. config change) ''start_service()'' is called by designed triggers. If it generates any different state (e.g. command will change) than the previous one, ''procd'' will detect it and restart the service. | The above information is stored by ''procd'' as a service instance state. On every relevant system change (e.g. config change), ''start_service()'' is called by designed triggers. If it generates any different state (e.g. command will change) than the previous one, ''procd'' will detect it and restart the service. |
| |
| Defining service instance details is handled by setting parameters. Some values are set directly in the ''start_service()'' (like ''command'') while some are determined by ''procd'' (like ''file'' and file hash). There are two helpers for setting parameters: | Defining service instance details is handled by setting parameters. Some values are set directly in the ''start_service()'' (like ''command'') while some are determined by ''procd'' (like ''file'' and file hash). There are two helpers for setting parameters: |
| - ''procd_append_param()'' | - ''procd_append_param()'' |
| |
| Below example lists supported parameters and describes them. For implementation details see the [[commit>?p=openwrt/openwrt.git;a=blob;f=package/system/procd/files/procd.sh|procd.sh]]. | The below example lists supported parameters and describes them. For implementation details see the [[commit>?p=openwrt/openwrt.git;a=blob;f=package/system/procd/files/procd.sh|procd.sh]]. |
| |
| <code> | <code bash> |
| start_service() { | start_service() { |
| procd_open_instance [instance_name] | procd_open_instance [instance_name] |
| |
| # respawn automatically if something died, be careful if you have an alternative process supervisor | # 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 | # if process exits sooner than respawn_threshold, it is considered crashed and after 5 retries the service is stopped |
| | # if process finishes later than respawn_threshold, it is restarted unconditionally, regardless of error code |
| | # notice that this is literal respawning of the process, not in a respawn-on-failure sense |
| procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} | 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 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 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 file /var/etc/your_service.conf # /etc/init.d/your_service reload will restart the daemon when these files have changed |
| procd_set_param netdev dev # likewise, except if dev's ifindex changes. | procd_set_param netdev dev # likewise, but for when dev's ifindex changes. |
| procd_set_param data name=value ... # likewise, except if this data changes. | procd_set_param data name=value ... # likewise, but for when this data changes. |
| procd_set_param stdout 1 # forward stdout of the command to logd | procd_set_param stdout 1 # forward stdout of the command to logd |
| procd_set_param stderr 1 # same for stderr | procd_set_param stderr 1 # same for stderr |
| ==== Init scripts during compilation ==== | ==== Init scripts during compilation ==== |
| |
| {{:meta:icons:tango:48px-dialog-warning.svg.png?32}}WARNING{{:meta:icons:tango:48px-dialog-warning.svg.png?32}}: 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. | {{:meta:icons:tango:48px-dialog-warning.svg.png?32}}WARNING{{:meta:icons:tango:48px-dialog-warning.svg.png?32}}: 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. |
| |
| ===== Specifying triggers ===== | ===== Specifying triggers ===== |
| Example: | Example: |
| |
| <code> | <code bash> |
| service_triggers() | service_triggers() |
| { | { |
| If some service requires a restart when ''reload'' is called, it can be implemented as follows: | If some service requires a restart when ''reload'' is called, it can be implemented as follows: |
| |
| <code> | <code bash> |
| reload_service() | reload_service() |
| { | { |
| </code> | </code> |
| |
| ==== Reloading service setup ==== | j==== Reloading service setup ==== |
| |
| Some services may support reloading configuration without a complete restart. It's usually implemented using `SIGHUP` or similar signal. | Some services may support reloading configuration without a complete restart. It's usually implemented using `SIGHUP` or similar signal. |
| </code> | </code> |
| |
| | <WRAP important> |
| | You can also configure reload by signal with ''procd_set_param reload_signal'' service option. |
| | </WRAP> |
| ===== Service jails ===== | ===== Service jails ===== |
| procd can isolate services using various Linux features typically used for (slim-)containers: //chroot// and //namespaces// (and //limits//, //seccomp//, //capabilities// as well as setting ''PR_SET_NO_NEW_PRIVS'', see [[#service_parameters|Service Parameters]]). | procd can isolate services using various Linux features typically used for (slim-)containers: //chroot// and //namespaces// (and //limits//, //seccomp//, //capabilities// as well as setting ''PR_SET_NO_NEW_PRIVS'', see [[#service_parameters|Service Parameters]]). |
| |
| ^ Function ^ Arguments ^ Description ^ | ^ Function ^ Arguments ^ Description ^ |
| | procd_add_jail | jail name, flags | Setup service jail (with features according to //flags//) | | | procd_add_jail | jail name, flags | Set up service jail (with features according to //flags//) | |
| | procd_add_jail_mount | read-only paths | Read-only bind the paths listed to the jail's mount namespace | | | procd_add_jail_mount | read-only paths | Read-only bind the paths listed to the jail's mount namespace | |
| | procd_add_jail_mount_rw | read-write paths | Bind the paths listed to the jail's mount namespace | | | procd_add_jail_mount_rw | read-write paths | Bind the paths listed to the jail's mount namespace | |
| | sysfs | Mount /sys in jail | | | sysfs | Mount /sys in jail | |
| | ronly | Re-mount jail rootfs read-only | | | ronly | Re-mount jail rootfs read-only | |
| | requirejail | Do not fallback to run without jail in case jail cannot be setup | | | requirejail | Do not fall back to run without jail in case jail could not be set up | |
| | netns | Run jailed process in new network namespace | | | netns | Run jailed process in new network namespace | |
| | userns | Run jailed process in new user namespace | | | userns | Run jailed process in new user namespace | |
| | cgroupsns | Run jailed process in new cgroups namespace | | | cgroupsns | Run jailed process in new cgroups namespace | |
| | console | Setup console accessible with ''ujail-console'' | | | console | Set up console accessible with ''ujail-console'' | |
| |
| See use cases of [[https://github.com/openwrt/packages/search?q=procd_add_jail|procd_add_jail]]. | See use cases of [[https://github.com/openwrt/packages/search?q=procd_add_jail|procd_add_jail]]. |