The can be convenient for running commands or services as procd services
without needing to separately write initscripts, just uci configuration.
The package was imported from [1].
[1] 0a85f5c75f/pservice
Ref: https://github.com/yousong/waller/issues/1
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
lilik-openwrt-22.03
@ -0,0 +1,28 @@ | |||
# Copyright (C) 2017 Yousong Zhou | |||
include $(TOPDIR)/rules.mk | |||
PKG_NAME:=pservice | |||
PKG_VERSION:=2017-08-29 | |||
PKG_RELEASE=1 | |||
PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com> | |||
include $(INCLUDE_DIR)/package.mk | |||
define Package/pservice | |||
SECTION:=utils | |||
CATEGORY:=Utilities | |||
TITLE:=Wrap commands as procd services | |||
endef | |||
define Build/Compile | |||
endef | |||
define Package/pservice/install | |||
$(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d $(1)/etc/config | |||
$(INSTALL_BIN) ./files/pservice.init $(1)/etc/init.d/pservice | |||
$(INSTALL_DATA) ./files/pservice.config $(1)/etc/config/pservice | |||
endef | |||
$(eval $(call BuildPackage,pservice)) |
@ -0,0 +1,44 @@ | |||
# uci | |||
`disabled`, bool, default `0` | |||
`name`, string, name of the service instance | |||
`command`, file, the service instance executable | |||
`args`, list of args | |||
`stderr`, bool, default `0`, log stderr output of the service instance | |||
`stdout`, bool, default `0`, log stdout output of the service instance | |||
`env`, list of environment variable settings of the form `var=val` | |||
`file`, list of file names. Service instances will be restarted if content of | |||
these files have changed on service reload event. | |||
`respawn_threshold`, uinteger, default `3600`, time in seconds the instances | |||
have to be in running state to be considered a valid run | |||
`respawn_timeout`, uinteger, default `5`, time in seconds the instance should | |||
be delayed to start again after the last crash | |||
`respawn_maxfail`, uinteger, default `5`, maximum times the instances can | |||
crash/fail in a row and procd will not try to bring it up again after this | |||
limit has been reached | |||
# notes and faq | |||
Initial environment variables presented to service instances may be different | |||
from what was observed on the interactive terminal. E.g. `HOME=/` may affect | |||
reading `~/.ssh/known_hosts` of dropbear ssh instance. | |||
PATH=/usr/sbin:/usr/bin:/sbin:/bin PWD=/ HOME=/ | |||
If `list args xxx` seems to be too long causing pain, consider using `/bin/sh` | |||
as the `command`. It is also worth noting that uci supports multi-line option | |||
value. | |||
Child processes will keep running when their parent process was killed. This | |||
is especially the case and should be taken into account with option `command` | |||
being `/bin/sh` and it is recommended to use `exec` as the last shell command. |
@ -0,0 +1,24 @@ | |||
config pservice | |||
option disabled 1 | |||
option name 'demo0' | |||
option command /bin/sh | |||
option respawn_maxfail 0 | |||
list args -c | |||
list args 'env | logger -t $name; exec sleep $time' | |||
list env 'v0=0' | |||
list env 'v1=val with space' | |||
list env 'name=demo0' | |||
list env 'time=1799' | |||
list file /tmp/sleep.conf | |||
config pservice | |||
option disabled 1 | |||
option name 8021x | |||
option command /usr/sbin/wpa_supplicant | |||
option stdout 1 | |||
list args -i | |||
list args eth0.1 | |||
list args -D | |||
list args wired | |||
list args -c | |||
list args /etc/wpa_supplicant-eth0.1.conf |
@ -0,0 +1,85 @@ | |||
#!/bin/sh /etc/rc.common | |||
# Copyright (C) 2017 Yousong Zhou | |||
START=99 | |||
USE_PROCD=1 | |||
pservice_list_cb() { | |||
local val="$1"; shift | |||
local param="$1"; shift | |||
procd_append_param "$param" "$val" | |||
} | |||
pservice() { | |||
local cfg="$1" | |||
eval "$(validate_pservice_section "$cfg" pservice_validate_mklocal)" | |||
validate_pservice_section "$cfg" || return 1 | |||
[ "$disabled" = 0 ] || return 0 | |||
[ -x "$command" ] || return 1 | |||
procd_open_instance "$name" | |||
procd_set_param command "$command" | |||
procd_set_param stderr "$stderr" | |||
procd_set_param stdout "$stdout" | |||
procd_set_param respawn "$respawn_threshold" "$respawn_timeout" "$respawn_maxfail" | |||
[ -z "$args" ] || config_list_foreach "$cfg" args pservice_list_cb command | |||
if [ -n "$env" ]; then | |||
procd_set_param env | |||
config_list_foreach "$cfg" env pservice_list_cb env | |||
fi | |||
if [ -n "$file" ]; then | |||
procd_set_param file | |||
config_list_foreach "$cfg" file pservice_list_cb file | |||
fi | |||
procd_close_instance | |||
} | |||
start_service() { | |||
config_load 'pservice' | |||
config_foreach pservice pservice | |||
} | |||
stop_service() { | |||
true | |||
} | |||
service_triggers() { | |||
procd_open_validate | |||
validate_pservice_section | |||
procd_close_validate | |||
} | |||
pservice_validate_mklocal() { | |||
local tuple opts | |||
shift 2 | |||
for tuple in "$@"; do | |||
opts="${tuple%%:*} $opts" | |||
done | |||
[ -z "$opts" ] || echo "local $opts" | |||
} | |||
pservice_validate() { | |||
uci_validate_section pservice "$@" | |||
} | |||
validate_pservice_section() { | |||
local cfg="$1"; shift | |||
local func="$1"; shift | |||
"${func:-pservice_validate}" pservice "$cfg" \ | |||
"disabled:bool:0" \ | |||
"name:string" \ | |||
"env:regex('^[a-zA-Z_][a-zA-Z0-9_]*=.*$')" \ | |||
"command:file" \ | |||
"args:list(string)" \ | |||
"stderr:bool:0" \ | |||
"stdout:bool:0" \ | |||
"respawn_threshold:uinteger:3600" \ | |||
"respawn_timeout:uinteger:5" \ | |||
"respawn_maxfail:uinteger:5" \ | |||
"file:string" | |||
} |