【问题标题】:Graceful kill off a detached node.js spawned child process in Windows在 Windows 中优雅地杀死一个分离的 node.js 产生的子进程
【发布时间】:2016-01-04 22:00:40
【问题描述】:

不是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 代码正在工作(或者可能不会因为SIGINT 将在没有readline 代码的情况下触发,但它仍然会触发SIGINT)

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

【问题讨论】:

  • 试试这个:spawn("taskkill", ["/pid", child.pid, '/f', '/t']);
  • @Louy 不重复,因为在该问题中,返回对子进程的引用,但这是从完全不同的节点进程中杀死子进程。此外,我已经在使用spawn,正如接受的答案中所建议的那样。
  • Windows 没有信号。 Node.js 可能会模拟跨进程信号,但这样做并不常见。
  • 为了澄清最后一条评论,windows 上的 process.kill 似乎可能会忽略信号类型,而只是终止目标进程。

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


【解决方案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')
})

这是我的调试输出

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

【讨论】:

    【解决方案2】:

    有一个库kill-with-style 可以执行此操作,并且也可以与分离的进程一起使用。它有多种设置信号、超时和重试选项的选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-27
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 2014-11-19
      相关资源
      最近更新 更多