无法在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
。 他们没有一个杀死孙子的过程 。
在inherit
和ignore
,父进程和subprocess(cmd.exe)都会被终止,但是subprocess仍然是浮动的,不属于任何进程树。
使用pipe
,只有subprocess终止,但父进程和macros进程继续运行。 父进程不存在的原因很可能是因为父节点的stdio仍然与原始回答中提到的其他进程共享。
child.unref()
对杀死grandsubprocess没有任何影响。 它只从父进程的事件循环中删除subprocess,以便父进程可以正常退出。
我可以想到几个解决scheme:
-
直接调用
babel.js
而不使用cmd脚本:var ps = child_process.spawn('node', ['.\\node_modules\\babel\\bin\\babel.js', 'input.js', '--out-file', 'output.js', '--watch'])
-
使用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,它使用taskkill
或tasklist
。
一个可能的解决scheme是调用ReadableStream.end
或ReadableStream.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);