Nodejs中childprocess为什么捕获不到SIGINT信号
Nodejs中childprocess为什么捕获不到SIGINT信号
father.js var spawn = require(‘child_process’).spawn; var child = spawn(‘node’,[‘child.js’]);
setInterval(function(){ child.kill(‘SIGINT’); },2000);
child.on(‘exit’,function(code,signal){ console.log('process exit ‘+code+’ '+signal); });
child.js process.stdin.resume(); process.on(‘SIGINT’, function() { console.log(‘Got SIGINT. Press Control-D to exit.’); });
为什么子进程捕获不到父进程的信号? 如果单独运行node child.js,通过ctrl+c,却可以捕捉到
Node.js 中 childprocess
为什么捕获不到 SIGINT
信号
在 Node.js 中使用 child_process
模块时,你可能会遇到一个问题:子进程无法捕获来自父进程的 SIGINT
信号。本文将探讨这个问题的原因,并提供一个示例来说明如何正确处理这种情况。
示例代码
首先,我们来看一下你的示例代码:
father.js
var spawn = require('child_process').spawn;
var child = spawn('node', ['child.js']);
setInterval(function(){
child.kill('SIGINT');
}, 2000);
child.on('exit', function(code, signal) {
console.log('Process exit ' + code + ' ' + signal);
});
child.js
process.stdin.resume();
process.on('SIGINT', function() {
console.log('Got SIGINT. Press Control-D to exit.');
});
问题分析
当你从父进程中发送 SIGINT
信号给子进程时,子进程可能无法捕获到该信号。这是因为 SIGINT
信号默认被传递给了主进程(即父进程),而不是子进程。
解决方案
要解决这个问题,我们需要确保子进程正确地捕获 SIGINT
信号。你可以通过修改子进程的代码来实现这一点。
改进后的 child.js
process.stdin.resume();
// 设置一个定时器来模拟长时间运行的任务
setTimeout(() => {}, 1000000);
process.on('SIGINT', function() {
console.log('Got SIGINT. Press Control-D to exit.');
process.exit(); // 退出子进程
});
改进后的 father.js
var spawn = require('child_process').spawn;
var child = spawn('node', ['child.js']);
setInterval(function(){
child.kill('SIGINT');
}, 2000);
child.on('exit', function(code, signal) {
console.log('Process exit ' + code + ' ' + signal);
});
解释
-
子进程代码修改:
- 在子进程中添加了一个长时间运行的任务(
setTimeout
),以模拟实际的应用场景。 - 子进程捕获
SIGINT
信号并输出一条消息,然后调用process.exit()
退出子进程。
- 在子进程中添加了一个长时间运行的任务(
-
父进程代码:
- 父进程每隔两秒向子进程发送一次
SIGINT
信号。 - 父进程监听子进程的
exit
事件,以便在子进程退出时打印相关信息。
- 父进程每隔两秒向子进程发送一次
通过这种方式,子进程能够正确地捕获 SIGINT
信号,并在接收到信号后正常退出。
node.js版本 0.10.17
首先fatcher.js中少了一句话
child.stdout.pipe(process.stdout);
其次运行在windows下不行,但在linux下正常工作,看来平台还是要选对啊。
在Node.js中,child_process
模块中的子进程默认不会继承父进程的标准输入流(stdin),因此当使用SIGINT
(通常是Ctrl+C)时,子进程可能无法捕获到这个信号。
在你的例子中,父进程试图向子进程发送SIGINT
信号,但子进程没有捕获到这个信号。这是因为SIGINT
信号默认不会被传递给子进程。子进程需要显式地启用对这些信号的处理。
示例代码修正
father.js
const { spawn } = require('child_process');
const child = spawn('node', ['child.js'], {
stdio: 'inherit' // 将标准输入流传递给子进程
});
setInterval(() => {
child.kill('SIGINT');
}, 2000);
child.on('exit', (code, signal) => {
console.log(`Process exited with code ${code} and signal ${signal}`);
});
child.js
process.stdin.resume(); // 确保子进程监听标准输入
process.on('SIGINT', () => {
console.log('Got SIGINT. Press Control-D to exit.');
});
解释
-
stdio: ‘inherit’:在创建子进程时,将
stdio
选项设置为'inherit'
,这样子进程会继承父进程的标准输入流。这使得子进程能够接收到SIGINT
信号。 -
process.stdin.resume():确保子进程监听标准输入流,以便正确处理
SIGINT
信号。 -
child.kill(‘SIGINT’):父进程发送
SIGINT
信号给子进程。由于设置了stdio: 'inherit'
,子进程能够捕获到这个信号。
通过这种方式,子进程就能够正确地捕获到父进程发送的SIGINT
信号了。