在Windows中优雅地杀死分离的node.js生成的子进程

时间:2016-01-04 22:00:41

标签: node.js windows command-line-interface kill

不是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是否不将信号类型发送到分离进程?如何检测到单独的脚本试图杀死我的子进程并正常关闭?

2 个答案:

答案 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 可以做到这一点,并且也适用于分离的进程。它有各种选项来设置信号、超时和重试选项。