以下内容永远不会退出
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);
这里发生了什么?这也是正确的做法?使此进程实际关闭的唯一方法是终止父进程。我怀疑它正在等待stdio冲洗或类似的东西?
如果给出'ignore'
stdio配置,它确实会死,但我需要这些流。
var ps = child_process.spawn('.\\node_modules\\.bin\\babel.cmd', ['test.js', '--out-file', 'output.js', '--watch'], {
stdio: 'ignore'
});
答案 0 :(得分:21)
您正在使用cmd.exe
生成子进程babel.cmd
。然后,此过程启动另一个孙进程node
并运行babel脚本。执行ps.kill()
时,它只会杀死cmd.exe
,但不会杀死由它创建的子进程。
虽然cmd.exe
已关闭,但父进程的stdio流仍与树中的其他进程共享。因此父进程正在等待关闭流。使用stdio: 'ignore'
只会停止与树中的其他进程共享stdio流,但这些孙进程仍将继续运行。
更新:
在与OP讨论后,我测试了所有三个stdio选项:iojs 3.3.0,Windows 7(32位)中的pipe
(默认),inherit
,ignore
。 他们都没有杀死孙子进程。
使用inherit
和ignore
,父进程和子进程(cmd.exe)都被终止,但是子进程仍然浮动并且不属于任何进程树。
使用pipe
时,只有子进程被终止,但父进程和子进程都继续运行。父进程未退出的原因很可能是因为父node.exe的stdio仍与原始答案中提到的其他进程共享。
child.unref()
对杀死大孩子进程没有任何影响。它只从父事件循环中删除子进程,以便父进程可以正常退出。
我能想到几个解决方案:
在没有该cmd脚本的情况下直接调用babel.js
:
var ps = child_process.spawn('node', ['.\\node_modules\\babel\\bin\\babel.js', 'input.js', '--out-file', 'output.js', '--watch'])
使用带有taskkill
标志的windows \T
命令来终止进程以及由它启动的所有子进程:
os = require('os');
if(os.platform() === 'win32'){
child_process.exec('taskkill /pid ' + ps.pid + ' /T /F')
}else{
ps.kill();
}
有一些npm模块可以处理在Unix和Windows中杀死子进程,例如tree-kill
。对于Windows,它使用taskkill
或tasklist
。
答案 1 :(得分:1)
一种可能的解决方案是致电ReadableStream.end
或ReadableStream.destroy
答案 2 :(得分: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);
答案 3 :(得分:0)
我在Windows上遇到了同样的问题(Win 10 64x)。我无法终止衍生的子进程的过程。
我使用service.windows
启动服务(自定义HTTP服务器child_process.spawn()
):
const { spawn } = require('child_process');
let cp = spawn('"C:\\Users\\user\\app\\service.windows"', [], { shell: true, });
cp.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
console.log('cp.connected', cp.connected);
console.log('process.pid', process.pid); // 6632 <<= main node.js PID
console.log('cp.pid', cp.pid); // 9424 <<= child PID
// All these are useless, they just kill `cp`
cp.kill('SIGINT'); // Doesn't terminate service.windows
cp.kill('SIGKILL'); // Doesn't terminate service.windows
cp.kill('SIGTERM'); // Doesn't terminate service.windows
});
我想终止我的HTTP服务器服务(service.windows
)。在使用cp.kill('ANY SIGNAL')
的Windows上无法实现。 Node.js终止其子进程(cp
),但我的HTTP服务器(service.windows
)仍然正常运行。
当我在其他终端检查时,我看到我的服务器运行正常:
$ netstat -ano | findstr :9090
TCP 0.0.0.0:9090 0.0.0.0:0 LISTENING 1340
TCP [::]:9090 [::]:0 LISTENING 1340
我尝试按PID
手动终止我的服务器,但T
标志,而不是F
。区别:
T
终止所有子进程以及父进程,通常称为树杀死。
F
进程被强制终止。
$ taskkill -T -PID 1340
ERROR: The process with PID 1340 (child process of PID 9424) could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
它确切地说我的服务器1340
是cp
- PID 9424
的孩子。
好的,我尝试再次使用cp
标志终止T
。繁荣,不可能。 cp
是我的主要节点的孩子.js process.pid
6632:
$ taskkill -T -PID 9424
ERROR: The process with PID 1340 (child process of PID 9424) could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process with PID 9424 (child process of PID 6632) could not be terminated.
Reason: One or more child processes of this process were still running.
我只能用F
标志强行杀死它:
$ taskkill -F -T -PID 9424
SUCCESS: The process with PID 1340 (child process of PID 9424) has been terminated.
SUCCESS: The process with PID 9424 (child process of PID 6632) has been terminated.
最令人失望的是,Node.js文档并没有说明如何处理这个问题。他们只是说'是的,我们知道这个问题存在,我们只是告诉你这个问题&#34;。
我在Windows上看到的唯一选项是在生成的进程中使用taskkill -F -T -PID 9424
:
exec('taskkill -F -T -PID 9424');