无法在Windows上杀死子进程

Cas*_*yer 10 node.js

以下将永远不会退出

var child_process = require('child_process');

var ps = child_process.spawn('.\\node_modules\\.bin\\babel.cmd', ['input.js', '--out-file', 'output.js', '--watch']);

ps.on('exit', function() {
  console.log('exit');
});

ps.on('close', function() {
  console.log('close');
});

setTimeout(function () {
  ps.kill();
}, 2000);
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?这也是正确的做法?使此进程实际关闭的唯一方法是终止父进程.我怀疑它正在等待stdio刷新或类似的东西?

如果给出'ignore'stdio配置它确实会死,但我需要流.

var ps = child_process.spawn('.\\node_modules\\.bin\\babel.cmd', ['test.js', '--out-file', 'output.js', '--watch'], {
    stdio: 'ignore'
});
Run Code Online (Sandbox Code Playgroud)

has*_*sin 21

您正在cmd.exe使用生成子进程babel.cmd.然后,此过程启动另一个孙子进程node 并运行babel脚本.当你这样做时ps.kill(),只会杀死它cmd.exe而不是它创建的子进程.

虽然cmd.exe已关闭,但父进程的stdio流仍与树中的其他进程共享.因此父进程正在等待关闭流.使用stdio: 'ignore'将仅停止与树中的其他进程共享stdio流,但这些孙进程仍将继续运行.


更新:

在与OP讨论后,我测试了所有三个stdio选项:( pipe默认)inherit,ignore在iojs 3.3.0,Windows 7(32位)中.他们都没有杀死孙子进程.

使用inheritignore,父进程和子进程(cmd.exe)都被终止,但是子进程仍然浮动并且不属于任何进程树.

使用时pipe,只有子进程终止,但父进程和子进程都继续运行.父进程未退出的原因很可能是因为父node.exe的stdio仍与原始答案中提到的其他进程共享.

child.unref()对杀死大孩子的过程没有任何影响.它只从父进程的事件循环中删除子进程,以便父进程可以正常退出.


我能想到几个解决方案:

  1. babel.js不使用该cmd脚本直接调用:

    var ps = child_process.spawn('node', ['.\\node_modules\\babel\\bin\\babel.js', 'input.js', '--out-file', 'output.js', '--watch'])
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用taskkill带有\T标志的windows 命令来终止进程以及由它启动的所有子进程:

    os = require('os');
    if(os.platform() === 'win32'){
        child_process.exec('taskkill /pid ' + ps.pid + ' /T /F')
    }else{
        ps.kill();  
    }
    
    Run Code Online (Sandbox Code Playgroud)

    有一些npm模块可以处理在Unix和Windows中杀死子进程,例如tree-kill.对于Windows使用taskkilltasklist.


Cas*_*yer 1

最直接的解决方案是,不要生成脚本,而是直接生成节点。

对于 unix,该脚本是 npm 可执行文件。然而,对于 Windows,我们需要从 .cmd 文件解析名称。

if (path.extname(command).toLowerCase() == '.cmd') {
  var content = '' + fs.readFileSync(command);
  var link = (/node  "%~dp0\\(.*?)"/.exec(content) || [])[1];

  if (link) {
    command = path.resolve(path.dirname(command), link);
  }
}

var ps = child.spawn('node', [command].concat(args), options);
Run Code Online (Sandbox Code Playgroud)