实际的服务器进程是由 shell 脚本生成的
我正在尝试为 djb 编写一个初始化脚本守护进程工具之内恩特软件在运行 busybox 1.24(ash shell)的路由器上。 daemontools 启动自身的方式是使用svscanbootshell 脚本。请注意,我已经删除了读取进程标题来自 svscanboot。
PATH=/opt/sbin:/opt/bin:/bin:/sbin:/usr/bin:/usr/sbin
exec </dev/null
exec >/dev/null
exec 2>/dev/null
/opt/bin/svc -dx /opt/service/* /opt/service/*/log
env - PATH=$PATH svscan /opt/service 2>&1
父 shell 脚本进程生成一个(后代)svscan
子进程,它是实际运行的服务器进程。
shell进程接收到TERM信号
运行svscanboot &
(在后台)并终止父进程会导致子进程运行:
# ps l | grep svscan
S 0 1526 1 1560 404 0:0 22:57 00:00:00 {svscanboot} /bin/sh /opt/bin/svscanboot
S 0 1528 1526 976 252 0:0 22:57 00:00:00 svscan /opt/service
# killall svscanboot
但 svscan 将继续运行
# ps l | grep svscan
S 0 1528 1 976 252 0:0 22:57 00:00:00 svscan /opt/service
执行svscanboot
(在前台)并终止父进程也会导致子进程仍在运行:
# ps l | grep svscan
S 0 676 671 1560 400 pts1 23:41 00:00:00 {svscanboot} /bin/sh /opt/bin/svscanboot
S 0 678 676 976 252 pts1 23:41 00:00:00 svscan /opt/service
# killall svscanboot
# ps l | grep svscan
S 0 678 1 976 252 pts1 23:41 00:00:00 svscan /opt/service
Busybox 非常有限,killall
只有标志-l
,-q
并且ps
只有w
ide、l
ong 和 showT
线程。
Ctrl当使用+退出前台版本时,C父进程和子进程都会终止。
在这种情况下如何停止父进程和子进程,最好使用killall
并最终通过修改svscanboot
?
答案1
执行
在我阅读了问题和答案后“exec env 命令”的含义一个可能的解决方案是在 前面env …
加上exec
.这将阻止子进程的产生。然而ps
输出{svscanboot} /bin/sh /opt/bin/svscanboot
。该名称svscan /opt/service
将更改为exec
.
或者捕获信号
处理此问题的另一种方法是通过陷阱将信号传播到子进程。喜欢在 Bash 中将 SIGTERM 转发给子进程或更详细的解释http://veithen.github.io/2014/11/16/sigterm-propagation.html
此解决方案路线的问题是-9
无法捕获 SIGKILL 又名信号号。
执行名称更改解决方法
由于无法捕获KILL信号,我将选择以下exec
路线:
…
exec env - PATH=$PATH svscan /opt/service 2>&1
由于名称更改,这仍然使在 Entware init 系统中停止/终止/重新配置“svscanboot”的事情变得复杂。 exec 进程名称更改需要一个解决方法。
模仿 svscanboot
entware-daemontools-init-script 可以更改为mimic svscanboot
,例如:
ENABLED=yes
#PRECMD="exec </dev/null;exec >/dev/null;exec 2>/dev/null;/opt/bin/svc -dx /opt/service/* /opt/service/*/log"
PROCS="svscan"
ARGS="/opt/service 2>&1"
PATH=/opt/sbin:/opt/bin:/sbin:/bin:/usr/sbin:/usr/bin
PREARGS="env - PATH=$PATH"
DESC="daemontools"
注释的 PRECMD 使得该操作svscan
不会启动。