supervisord 没有在停止命令时杀死所有产生的节点进程

问题描述

我在使用 supervisord 部署新服务时遇到了一些奇怪的事情。这些是相关部分:

# supervisord.conf

[program:express]
command=yarn re-express-start
# package.json
{
  "scripts": {
    "re-express-start": "node lib/js/client/Express.bs.js",}
}

当我运行 supervisorctl start 时,节点服务器按预期启动。但是在我运行 supervisorctl stop 后,即使主管认为它已被杀死,服务器仍继续运行。

如果我将 supervisord.conf 文件更改为直接执行 node lib/js/client/Express.bs.js(不经过 yarn),那么这将按预期工作。但我想通过 package.json 定义的脚本。

我查看了流程树的外观,但我不太明白为什么。下面是停止supervisord-managed服务前后的流程。

$ ps aux | grep node
user     12785  1.4  3.5 846404 72912 ?        Sl   16:30   0:00 node /usr/bin/yarn re-express-start
user     12796  0.0  0.0   4516   708 ?        S    16:30   0:00 /bin/sh -c node lib/js/client/Express.bs.js
user     12797  5.2  2.7 697648 56384 ?        Sl   16:30   0:00 /usr/bin/node lib/js/client/Express.bs.js
root     12830  0.0  0.0  14216  1004 pts/1    S+   16:30   0:00 grep --color=auto node

$ pstree -c -l -p -s 12785
systemd(1)───supervisord(7153)───node(12785)─┬─sh(12796)───node(12797)─┬─{node}(12798)
                                             │                         └─{node}(12807)
                                             ├─{node}(12786)
                                             └─{node}(12795)

$ supervisorctl stop express

$ ps aux | grep node
user     12797  0.7  2.7 697648 56384 ?        Sl   16:30   0:00 /usr/bin/node lib/js/client/Express.bs.js
root     12975  0.0  0.0  14216   980 pts/1    S+   16:32   0:00 grep --color=auto node

$ pstree -c -l -p -s 12797
systemd(1)───node(12797)─┬─{node}(12798)
                         └─{node}(12807)

$ kill 12797

$ ps aux | grep node
root     13426  0.0  0.0  14216   976 pts/1    S+   16:37   0:00 grep --color=auto node

从上面可以看出,执行服务器工作的“实际”工作负载进程具有 PID 12797。它由主管进程产生并嵌套在更多进程之下。 停止监督进程会停止具有 1278512796 PID 的进程,但不是 12797 实际上重新附加到 init 进程。

对这里发生的事情有什么想法吗?这是因为某事忽略了一些 SIGxxx 信号吗?我认为这是 yarn 调用以某种方式吃掉了那些, 但我不知道如何以及如何重新配置​​。

解决方法

我在运行 node Express 应用程序时也遇到了这个问题。问题似乎是我有主管调用 npm start,它指的是 package.json start 脚本。该脚本只是调用 node app.js。解决方案似乎是直接从主管配置文件中调用该命令,如下所示:

[program:node]
...
command=node app.js
...
stopasgroup=true
stopsignal=QUIT

此外,我添加了 stopasgroup 并将 stopsignal 更改为 QUIT。似乎需要停止信号才能正确终止进程。

我现在可以自由调用 supervisorctl restart node:node_00 而不会出现任何 ERROR (spawn error) 错误。