【问题标题】:How to guarantee Supervisor-launched script gets killed when daemon stopped?当守护进程停止时,如何保证主管启动的脚本被杀死?
【发布时间】:2022-11-15 11:31:00
【问题描述】:

您如何确保运行sudo supervisorctl stop myservice 确实停止了我的服务?

我有一个主管配置,如:

[program:myprogram]
command=/usr/local/bin/run_script.sh
directory=/usr/local/bin
user=myuser
numprocs=1
process_name=%(program_name)s
stdout_logfile=/var/log/run_script.log
stderr_logfile=/var/log/run_script.log
autostart=true
autorestart=true
startsecs=10
stopsignal=KILL

文件run_script.sh 进行一些 shell 初始化,然后启动一个单独的 Python 脚本,run_script.py,它通过joblib.Parallel 阻止但运行一些多个进程。

当我启动守护进程时,Supervisor 启动它很好。但是,当我运行sudo supervisorctl stop myprogram 时,守护程序永远不会停止,即使主管将它们列为已停止。几分钟后,如果我运行ps aux | grep -i run_script,我可以看到 .sh 和 .py 脚本都在运行。

为什么 Supervisor 无法停止守护进程?

我已经指定了 KILL 停止信号。启动 Python 脚本的 Bash 脚本是否存在一些问题,Python 脚本本身会启动多进程,这会阻止 Supervisor 正确停止进程?

【问题讨论】:

    标签: python supervisord


    【解决方案1】:

    这里发生了两件事。

    1. Supervisord 知道其直系子代的 PID,但不知道所有子代的 PID。
    2. 我们正在发送无法捕获的 KILL (9) 而不是 TERM (15)。

      这两个人不会相处得很好。


      当前层次结构是:bash --> python --> python workers

      现在,如果是只是“庆典——>蟒蛇”, 我们可能会通过exec python myservice.py 解决您的问题, 将层次结构分解为仅一个进程。 最初它是一个 pid 为 123 的 bash 进程, 然后是一个 python 进程,仍然是 pid 123, 感谢执行官。

      但考虑到工人,这还不够, 我们需要进一步挖掘。


      您在抱怨“我发送了 SIGKILL 并且没有发生正确的事情!”

      嗯,当然没有,你没有 给“myservice”一个清理的机会 了它的孩子。

      (当我想到它时,结束 bash 带有“exec python ...”的脚本将是 方便,因为那样我们就少了一个 需要担心的信号处理程序。)

      发送 SIGTERM (15) 到你的 python 过程,并验证它

      • 捕捉到信号
      • 发送 SIGTERM 给它的孩子
      • 退出

      我希望一切都发生在 默认,但你当然可以写 调试和执行的 TERM 处理程序 任何额外的清理项目 是需要的。 可能有一个子 PID 列表 方便,或者我们可能想发送 到 PID 零,所以它被传送到 过程组中的每个人, 就像 killpg() 会做的那样。

      如果孩子不乖, 您的自定义处理程序可能想 超时后发送 KILL (9)。 我建议你只坚持 TERM 如果你能逃脱的话。

    【讨论】:

      最近更新 更多