不是this的副本:我可以杀死进程,我想知道如何在进程中检测到它被杀死并正常关闭。
我有一个CLI工具来生成并终止子node.js进程。演示代码包含在以下三个文件中:
spawn.js
- 将生成child.js
脚本,已分离。为简单起见,我将孩子的stdio
发送到out.log
文件
child.js
- 一个写入文件的简单计数器,使用readline
方法在Windows中检测模拟的SIGINT
kill.js
- 在子进程上调用process.kill()
,使用它的PID
spawn.js
'use strict';
var spawn = require('child_process').spawn;
var fs = require('fs');
var path = require('path');
var childFilePath = path.resolve(__dirname, 'child.js');
var out = fs.openSync('./out.log', 'a');
var err = fs.openSync('./out.log', 'a');
var options = {
detached: true,
stdio: ['ignore', out, err],
};
var child = spawn(process.execPath, [childFilePath], options);
child.unref();
child.js
'use strict';
var fs = require('fs');
var path = require('path');
if (process.platform === 'win32') {
console.log('win32 true');
var rl = require('readline').createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on('SIGINT', function() {
process.emit('SIGINT');
});
}
process.on('SIGINT', function() {
console.log('SIGINT');
process.exit();
});
var filepath = path.resolve(__dirname, 'pid.txt');
fs.writeFile(filepath, process.pid);
var i = 0;
setInterval(function () {
console.log(i++);
}, 1000);
kill.js
'use strict';
var fs = require('fs');
var path = require('path');
var pidPath = path.resolve(__dirname, 'pid.txt');
fs.readFile(pidPath, 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
process.kill(data, 'SIGINT');
});
发送process.kill(PID, 'SIGINT')
时,它实际上并未在Windows中将其检测为SIGINT
。我可以手动运行child.js
并使用CTRL+C
来终止进程以触发SIGINT
,因此我知道readline
代码正在运行(或者可能不是{{1}将在没有SIGINT
代码的情况下触发,但它仍会触发readline
)
SIGINT
是否不将信号类型发送到分离进程?如何检测到单独的脚本试图杀死我的子进程并正常关闭?
答案 0 :(得分:0)
我有完全相同的问题。我注意到rl.on("SIGINT")
无效但rl.on("close")
无效!
var rl = require('readline').createInterface({
input: process.stdin,
output: process.stdout,
})
rl.on('close', function() {
process.emit('SIGINT')
})
这是我的调试输出
Sat Feb 17 2018 11:43:28 GMT+0800 (China Standard Time) process started (pid=6920)
Sat Feb 17 2018 11:43:28 GMT+0800 (China Standard Time) SIGINT captured! cleanup and then call process.exit(0)
Sat Feb 17 2018 11:43:28 GMT+0800 (China Standard Time) byebye! (code=0, signal=undefined)
请注意,我不确定向子进程添加额外代码是个好主意。考虑分叉非nodejs进程,它可能无法使用这种技巧(例如redis-server,kdb +)。我仍在寻找让spawn.js
优雅地杀死子进程的方法。
更新1:这是我向PM2社区报告的初始问题 https://github.com/Unitech/pm2/issues/3467
答案 1 :(得分:0)
有一个库 kill-with-style 可以做到这一点,并且也适用于分离的进程。它有各种选项来设置信号、超时和重试选项。