Node.js - process.exit()vs childProcess.kill()

h9vpoimq  于 2023-06-22  发布在  Node.js
关注(0)|答案(3)|浏览(111)

我有一个节点应用程序,它运行长时间运行的任务,所以每当一个任务运行时,就会派生一个子进程来运行该任务。代码为要运行的任务创建一个fork,并向子进程发送一条消息以启动。
最初,当任务完成时,我向父进程发送一条消息,父进程将对子进程调用.kill()。我在活动监视器中注意到节点进程没有被删除。所有子进程都挂起。因此,我没有向父进程发送消息并调用.kill(),而是在任务完成后在子进程代码中调用process.exit()。
第二种方法似乎工作正常,我看到节点进程从活动监视器中删除,但我想知道这种方法是否有我不知道的缺点。一种方法比另一种更好吗?这两种方法有什么区别?
对于消息传递方法,我的代码如下所示。

//Parent process
    const forked = fork('./app/jobs/onlineConcurrency.js');
    forked.send({clientId: clientData.clientId, 
            schoolYear: schoolYear
        });
    forked.on("message", (msg) => {
        console.log("message", msg);
        forked.kill();
    });

//child Process 
process.on('message', (data) => {
    console.log("Message recieved");
    onlineConcurrencyJob(data.clientId, data.schoolYear, function() {
        console.log("Killing process");
        process.send("done");
    });
})

子进程退出时的代码如下所示

//child Process 
process.on('message', (data) => {
    console.log("Message received");
    onlineConcurrencyJob(data.clientId, data.schoolYear, function() {
        console.log("Killing process");
        process.exit();
    });
})
ddhy6vgd

ddhy6vgd1#

kill向子进程发送信号。在没有参数的情况下,它发送一个SIGTERM(其中TERM是“termination”的缩写),顾名思义,它通常会终止进程。
然而,发送这样的信号是停止进程的强制方法。如果进程正在执行写入文件等任务,并且收到终止信号,则可能会导致文件损坏,因为进程没有机会将所有数据写入文件并关闭它(对此有缓解措施,比如安装一个信号处理程序,可以用来“捕获”信号并忽略它们,或者在退出之前完成所有任务但这需要将显式代码添加到子进程)。
而在process.exit()中,进程 * 自身 * 退出。通常,它在知道没有更多的挂起任务时这样做,因此它可以干净地退出。一般来说,这是停止(子)进程的最佳方式。
至于为什么这些进程没有被删除,我不确定。可能父进程没有清理子进程的资源,但我希望这会自动发生(我甚至不认为你可以在Node.js中显式地执行所谓的“子进程收割”)。

jdgnovmf

jdgnovmf2#

调用process.exit(0)是最好的机制,尽管在某些情况下,您可能希望从父级调用.kill(例如,.kill)。分布式搜索,其中一个节点返回意味着所有节点可以停止)。
.kill可能是由于对它接收到的信号进行了一些处理而失败的。尝试.kill('SIGTERM'),甚至是'SIGKILL'。
还要注意,当父进程退出时没有被杀死的子进程将被移动到祖父进程。有关更多信息和建议的解决方案,请参见此处:https://github.com/nodejs/node/issues/13538
总之,这是默认的Unix行为,解决方法是process.on("exit", () => child.kill())

slhcrj9b

slhcrj9b3#

对我来说,杀死.exec()子进程唯一有效的方法是在尝试使用kill的每一个信号都不起作用后使用npm库terminate。但是terminate做到了。具体操作如下:

const terminate = require('terminate')
terminate(myProcess.pid, err => console.log(err))

其中myProcess简单地是:const myProcess = childProcess.exec(...)。您不需要在子进程上使用{ detached: true },这不是必要的。
您可以使用以下命令安装terminate:yarn add terminate
这一招非常有效。

相关问题