无法在Windows上杀死subprocess

以下将永远不会退出

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); 

这里发生了什么? 在这里做什么是正确的事情呢? 使这个过程真正closures的唯一方法是杀死父进程。 我怀疑这是等待stdio刷新或类似的东西?

如果它被赋予'ignore' stdioconfiguration,它会死亡,但是我需要stream。

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

您正在使用babel.cmd产生subprocesscmd.exe 。 这个过程然后启动另一个孙subprocessnode并运行babel脚本。 当你做ps.kill()它只会杀死cmd.exe而不会杀死它创build的subprocess。

尽pipecmd.exe已closures,但父进程的stdiostream仍与树中的其他进程共享。 所以父进程正在等待stream被closures。 使用stdio: 'ignore'只会停止与树中的其他进程共享stdiostream,但这些孙subprocess仍将继续运行。


更新:

与OP讨论后,我testing了所有三个stdio选项: pipe (默认), inherit ,在iojs 3.3.0,Windows 7(32位) ignore他们没有一个杀死孙子的过程

inheritignore ,父进程和subprocess(cmd.exe)都会被终止,但是subprocess仍然是浮动的,不属于任何进程树。

使用pipe ,只有subprocess终止,但父进程和macros进程继续运行。 父进程不存在的原因很可能是因为父节点的stdio仍然与原始回答中提到的其他进程共享。

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


我可以想到几个解决scheme:

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

     var ps = child_process.spawn('node', ['.\\node_modules\\babel\\bin\\babel.js', 'input.js', '--out-file', 'output.js', '--watch']) 
  2. 使用windows taskkill命令和\T标志来杀死进程和所有由它启动的subprocess:

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

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

一个可能的解决scheme是调用ReadableStream.endReadableStream.destroy

最直接的解决scheme,不要派生脚本,而是直接产生节点。

对于unix,脚本是npm可执行文件。 对于Windows,我们需要从.cmd文件中parsing名称。

 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);