在 Windows 中优雅地终止独立的 node.js 生成的子进程

PGT*_*PGT 6 windows kill command-line-interface node.js

不是重复的我可以很好地终止进程,我想知道如何在进程内检测它正在被终止,并优雅地关闭。

概述:

我有一个 CLI 工具来生成和终止子 node.js 进程。演示代码包含在这三个文件中:

spawn.js-- 将生成child.js脚本,分离。为了简单起见,我将孩子的管道传输stdio到一个out.log文件

child.js-- 写入文件的简单计数器,使用该readline方法检测 Windows 中的模拟 SIGINT

kill.jsprocess.kill()--使用子进程的 PID调用 a


代码:

生成.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();
Run Code Online (Sandbox Code Playgroud)

孩子.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);
Run Code Online (Sandbox Code Playgroud)

杀戮.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');
});
Run Code Online (Sandbox Code Playgroud)

问题:

发送 时process.kill(PID, 'SIGINT'),它实际上并未将其检测为SIGINTWindows 中的 。我可以child.js手动运行并使用CTRL+C来终止进程来触发 a SIGINT,所以我知道readline代码正在工作(或者可能不会,因为SIGINT没有代码就会触发readline,但它仍然会触发 a SIGINT

process.kill()向分离进程发送信号类型?如何检测到一个单独的脚本正在尝试终止我的子进程并正常关闭?

sta*_*005 1

我也有完全一样的问题。我注意到它rl.on("SIGINT")不起作用但rl.on("close")有效!

var rl = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout,
})

rl.on('close', function() {
    process.emit('SIGINT')
})
Run Code Online (Sandbox Code Playgroud)

这是我的调试输出

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)
Run Code Online (Sandbox Code Playgroud)

请注意,我不太确定向子流程添加额外的代码是个好主意。想想fork一个非nodejs进程,它可能无法使用这样的技巧(例如redis-server,kdb+)。我仍在寻找一种方法来spawn.js优雅地终止子进程。

更新 1:这是我向 PM2 社区报告的最初问题 https://github.com/Unitech/pm2/issues/3467