简体   繁体   English

优雅地杀死了一个分离的 node.js 在 Windows 中产生的子进程

[英]Graceful kill off a detached node.js spawned child process in Windows

Not a duplicate of this : I can kill process fine, I want to know how to detect, within the process, that it's being killed, and gracefully shutdown.不是这个的重复:我可以很好地杀死进程,我想知道如何在进程中检测到它正在被杀死,然后优雅地关闭。

Overview:概述:

I have a CLI tool to spawn and kill a child node.js process.我有一个 CLI 工具来生成和终止子进程 node.js。 The demo code is contained in these three files:演示代码包含在这三个文件中:

spawn.js -- Will spawn the child.js script, detached. spawn.js将生成child.js脚本,分离。 For simplicity, I pipe the child's stdio to an out.log file为简单起见,我 pipe 孩子的stdio到一个out.log文件

child.js -- A simple counter which writes to a file, uses the readline method to detect an emulated SIGINT in Windows child.js -- 一个写入文件的简单计数器,使用readline方法检测 Windows 中的模拟 SIGINT

kill.js -- Invokes a process.kill() on the child process, using it's PID kill.js -- 在子进程上调用process.kill() ,使用它的 PID


Code:代码:

spawn.js 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孩子.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 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');
});

Problem:问题:

When sending the process.kill(PID, 'SIGINT') , it doesn't actually detect it as a SIGINT in windows. I can run child.js manually and use CTRL+C to kill the process to trigger a SIGINT , so I know that the readline code is working (or maybe not since SIGINT will trigger without the readline code, but it will n.netheless trigger a SIGINT )发送process.kill(PID, 'SIGINT')时,它实际上并没有将其检测为 windows 中的SIGINT 。我可以手动运行child.js并使用CTRL+C终止进程以触发SIGINT ,所以我知道readline代码正在工作(或者可能不是,因为SIGINT将在没有readline代码的情况下触发,但它会 n.netheless 触发SIGINT

Does process.kill() not send the type of signal to a detached process? process.kill()不会将信号类型发送到分离进程吗? How do I detect that that a separate script is trying to kill my child process and shutdown gracefully?我如何检测到一个单独的脚本试图终止我的子进程并正常关闭?

I have exactly the same problem. 我也有完全一样的问题。 I noticed the rl.on("SIGINT") is not working but rl.on("close") works! 我注意到rl.on("SIGINT")不起作用但rl.on("close")有效!

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

rl.on('close', function() {
    process.emit('SIGINT')
})

Here is my debug output 这是我的调试输出

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)

Note that I'm not pretty sure that adding extra code to a subprocess is a good idea. 请注意,我不太确定向子进程添加额外的代码是个好主意。 Think about forking a non nodejs process, it might not be able to use such trick (eg redis-server, kdb+). 考虑分叉非nodejs进程,它可能无法使用这样的技巧(例如redis-server,kdb +)。 I am still looking for a way to let spawn.js to kill subprocess gracefully. 我仍在寻找一种方法让spawn.js优雅地杀死子spawn.js

Update 1: Here is my initial problem reported to PM2 community https://github.com/Unitech/pm2/issues/3467 更新1:这是我向PM2社区报告的初始问题https://github.com/Unitech/pm2/issues/3467

There is a library kill-with-style to do this and works with detached process too.有一个库kill-with-style可以执行此操作,并且也可以与分离进程一起使用。 It has various options to set signal, timeout and retry options.它有多种选项来设置信号、超时和重试选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM