Kill

如何正確停止busybox shell程序和子程序?

  • January 14, 2021

實際的伺服器程序由 shell 腳本生成

我正在嘗試在執行busybox 1.24(ash shell)的路由器上的Entware中為djb daemontools編寫一個初始化腳本。daemontools 啟動自身的方式是使用svscanboot shell 腳本。請注意,我已從svscanboot中刪除了 readproctitle。

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只有wide、long 和 showT執行緒。

Ctrl並且當使用+退出前台版本時,C父程序和子程序都會終止。

在這種情況下如何停止父程序和子程序,最好使用killall並最終通過修改svscanboot

執行

在我閱讀了“exec env COMMAND”的含義的問題和答案之後,一個可能的解決方案可能是在前面env …加上exec. 這將防止產生子程序。然而ps輸出{svscanboot} /bin/sh /opt/bin/svscanbootsvscan /opt/service該名稱將更改為exec.

或擷取信號

處理此問題的另一種方法是通過將信號傳播到子程序的陷阱。就像在 Bash 中將 SIGTERM 轉發給孩子或更詳細地解釋了http://veithen.github.io/2014/11/16/sigterm-propagation.html 此解決方案路線的問題是-9不能擷取SIGKILL aka 信號編號.

執行名稱更改解決方法

由於無法擷取 KILL 信號,我將選擇exec路由:

…
exec env - PATH=$PATH svscan /opt/service 2>&1

由於名稱已更改,這仍然會使在 Entware 初始化系統中停止/殺死/重新配置“svscanboot”變得複雜。該 exec 程序名稱更改將需要解決方法。

模仿 svscanboot

entware-daemontools-init-script 可以更改為模仿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不會啟動。

引用自:https://unix.stackexchange.com/questions/326685