Node.js - process.exit() 对比 childProcess.kill()
Node.js - process.exit() vs childProcess.kill()
我有一个 运行s 长 运行ning 任务的节点应用程序,所以每当任务 运行s 一个子进程被派生到 运行 任务。该代码为任务创建一个分支 运行 并向子进程发送消息以启动。
最初,当任务完成时,我正在向父进程发回消息,父进程会在子进程上调用 .kill() 。我在 activity 监视器中注意到节点进程没有被删除。所有的子进程都在附近徘徊。因此,我没有向父进程发送消息并调用 .kill(),而是在任务完成后在子进程代码中调用 process.exit()。
第二种方法似乎工作正常,我看到节点进程已从 activity 监视器中删除,但我想知道这种方法是否有我不知道的缺点。一种方法比另一种更好吗?这两种方法有什么区别?
我的消息传递方法代码如下所示。
//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();
});
})
kill
向子进程发送信号。如果没有参数,它会发送一个 SIGTERM
(其中 TERM
是 "termination" 的缩写),顾名思义,它通常会终止进程。
但是,发送这样的信号是一种强制停止进程的方法。如果进程正在执行诸如写入文件之类的任务,并且它收到终止信号,则可能会导致文件损坏,因为进程没有机会将所有数据写入文件并关闭它(对此有缓解措施,就像安装一个信号处理程序,可以用于 "catch" 信号并忽略它们,或者在退出之前完成所有任务,但这需要将显式代码添加到子进程)。
而对于 process.exit()
,进程退出 本身 。通常,它会在知道没有更多未决任务时这样做,因此它可以干净地退出。一般来说,这是停止(子)进程的最佳方式。
至于为什么没有删除进程,我不确定。可能是父进程没有清理子进程的资源,但我希望它会自动发生(我什至不认为你可以在 [=28] 中显式执行所谓的 "child reaping" =]).
调用 process.exit(0)
是最好的机制,尽管在某些情况下您可能希望从父节点 .kill
调用(例如分布式搜索,其中一个节点返回意味着所有节点都可以停止)。
.kill
可能由于对其接收到的信号进行了一些处理而失败。尝试 .kill('SIGTERM')
,甚至 'SIGKILL'。
另请注意,当父进程退出时未被杀死的子进程将被移动到祖父进程。有关详细信息和建议的解决方法,请参阅此处:https://github.com/nodejs/node/issues/13538
总而言之,这是默认的 Unix 行为,解决方法是 process.on("exit", () => child.kill())
我有一个 运行s 长 运行ning 任务的节点应用程序,所以每当任务 运行s 一个子进程被派生到 运行 任务。该代码为任务创建一个分支 运行 并向子进程发送消息以启动。
最初,当任务完成时,我正在向父进程发回消息,父进程会在子进程上调用 .kill() 。我在 activity 监视器中注意到节点进程没有被删除。所有的子进程都在附近徘徊。因此,我没有向父进程发送消息并调用 .kill(),而是在任务完成后在子进程代码中调用 process.exit()。
第二种方法似乎工作正常,我看到节点进程已从 activity 监视器中删除,但我想知道这种方法是否有我不知道的缺点。一种方法比另一种更好吗?这两种方法有什么区别?
我的消息传递方法代码如下所示。
//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();
});
})
kill
向子进程发送信号。如果没有参数,它会发送一个 SIGTERM
(其中 TERM
是 "termination" 的缩写),顾名思义,它通常会终止进程。
但是,发送这样的信号是一种强制停止进程的方法。如果进程正在执行诸如写入文件之类的任务,并且它收到终止信号,则可能会导致文件损坏,因为进程没有机会将所有数据写入文件并关闭它(对此有缓解措施,就像安装一个信号处理程序,可以用于 "catch" 信号并忽略它们,或者在退出之前完成所有任务,但这需要将显式代码添加到子进程)。
而对于 process.exit()
,进程退出 本身 。通常,它会在知道没有更多未决任务时这样做,因此它可以干净地退出。一般来说,这是停止(子)进程的最佳方式。
至于为什么没有删除进程,我不确定。可能是父进程没有清理子进程的资源,但我希望它会自动发生(我什至不认为你可以在 [=28] 中显式执行所谓的 "child reaping" =]).
调用 process.exit(0)
是最好的机制,尽管在某些情况下您可能希望从父节点 .kill
调用(例如分布式搜索,其中一个节点返回意味着所有节点都可以停止)。
.kill
可能由于对其接收到的信号进行了一些处理而失败。尝试 .kill('SIGTERM')
,甚至 'SIGKILL'。
另请注意,当父进程退出时未被杀死的子进程将被移动到祖父进程。有关详细信息和建议的解决方法,请参阅此处:https://github.com/nodejs/node/issues/13538
总而言之,这是默认的 Unix 行为,解决方法是 process.on("exit", () => child.kill())