Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
docs:guide-developer:procd-init-scripts [2021/01/14 18:07] – [procd init script parameters] ssbdocs:guide-developer:procd-init-scripts [2024/02/10 16:23] (current) – [Defining service instances] systemcrash
Line 1: Line 1:
-======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
Line 9: Line 9:
  
 Example: Example:
-<code>+<code bash>
 #!/bin/sh /etc/rc.common #!/bin/sh /etc/rc.common
  
Line 36: Line 36:
   - 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:
Line 42: Line 42:
   - ''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]
Line 51: Line 51:
  
          # 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
          procd_set_param user nobody # run service as user nobody          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_set_param pidfile /var/run/somefile.pid # write a pid file on instance start and remove it on stop
 +         procd_set_param term_timeout 60 # wait before sending SIGKILL
          procd_close_instance          procd_close_instance
 } }
Line 69: Line 72:
 ==== Stopping services ==== ==== Stopping services ====
  
-''stop_service()'' is only needed when you need special things to stop your service. ''stop_service()'' is called //after// procd killed the service.+''stop_service()'' is only needed when you need special things to stop your service. ''stop_service()'' is called //before// procd killed the service
 + 
 +If you want to add a check //after// procd has sent the terminate signal (e.g. wait for the process to be really gone), you can define an extra function ''service_stopped()''.
  
 ==== 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 =====
Line 85: Line 90:
 Example: Example:
  
-<code>+<code bash>
 service_triggers() service_triggers()
 { {
         procd_add_reload_trigger "<uci-file-name>" "<second-uci-file>"         procd_add_reload_trigger "<uci-file-name>" "<second-uci-file>"
         procd_add_reload_interface_trigger <interface>         procd_add_reload_interface_trigger <interface>
 +        procd_add_reload_mount_trigger <path> [<path> ...]
 } }
 </code> </code>
Line 96: Line 102:
 | procd_add_reload_trigger           | list of config files | ''config.change'' | Uses ''/etc/init.d/<foo> reload'' as the handler | | procd_add_reload_trigger           | list of config files | ''config.change'' | Uses ''/etc/init.d/<foo> reload'' as the handler |
 | procd_add_reload_interface_trigger | interface name       | ''interface.*''   | Uses ''/etc/init.d/<foo> reload'' as the handler | | procd_add_reload_interface_trigger | interface name       | ''interface.*''   | Uses ''/etc/init.d/<foo> reload'' as the handler |
 +| procd_add_reload_mount_trigger     | paths to watch for   | ''mount.add''     | Uses ''/etc/init.d/<foo> reload'' as the handler |
 +| procd_add_restart_mount_trigger    | paths to watch for   | ''mount.add''     | Uses ''/etc/init.d/<foo> restart'' as the handler |
  
 <WRAP important> <WRAP important>
Line 109: Line 117:
 </WRAP> </WRAP>
  
-See use cases of [[https://github.com/openwrt/packages/search?q=procd_add_interface_trigger|procd_add_interface_trigger]] and [[https://github.com/openwrt/packages/search?q=procd_add_reload_trigger|procd_add_reload_trigger]] in the OpenWrt packages repository.+<WRAP important> 
 +Using mount triggers depends on mount notifications emitted by ''blockd''. Hence ''blockd'' needs to be installed and the mount need to be configured in ''/etc/config/fstab''
 + 
 +See also [[:docs:guide-user:storage:fstab]] 
 +</WRAP> 
 + 
 +See use cases of [[https://github.com/openwrt/packages/search?q=procd_add_interface_trigger|procd_add_interface_trigger]][[https://github.com/openwrt/packages/search?q=procd_add_reload_trigger|procd_add_reload_trigger]], [[https://github.com/openwrt/packages/search?q=procd_add_reload_mount_trigger|procd_add_reload_mount_trigger]] in the OpenWrt packages repository.
  
 ==== ucitrack ==== ==== ucitrack ====
Line 129: Line 143:
 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()
 { {
Line 138: Line 152:
 </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.
Line 162: Line 176:
 procd_send_signal service_name [instance_name] [signal] procd_send_signal service_name [instance_name] [signal]
 </code> </code>
 +
 +<WRAP important>
 +You can also configure reload by signal with ''procd_set_param reload_signal'' service option.
 +</WRAP>
 +===== 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]]).
 +
 +^ Function                ^ Arguments            ^ Description                                                        ^
 +| 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_rw | read-write paths     | Bind the paths listed to the jail's mount namespace                |
 +
 +^ Flag        ^ Description                                                      ^
 +| log         | Allow jailed service to log to syslog                            |
 +| ubus        | Allow jailed service to access ubus                              |
 +| procfs      | Mount /proc in jail                                              |
 +| sysfs       | Mount /sys in jail                                               |
 +| ronly       | Re-mount jail rootfs read-only                                   |
 +| 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                      |
 +| userns      | Run jailed process in new user namespace                         |
 +| cgroupsns   | Run jailed process in new cgroups namespace                      |
 +| 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]].
  
 ===== Debugging ===== ===== Debugging =====
 +
 Set PROCD_DEBUG=1 to see debugging information when starting or stopping a procd init script. 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. Also, ''INIT_TRACE=1 /etc/init.d/mything $action'' Where $action is start/stop etc.
 +
 ===== Examples ===== ===== Examples =====
  
  • Last modified: 2021/01/14 18:07
  • by ssb