我使用spawn
创建子进程和管道数据:
child process | parent process (main)
---------------------------------------
stdout -----> process.stdout
stderr -----> process.stderr
stdin <----- process.stdin
问题在于,当process.stdin
管道到子进程stdin
时,子进程完成时主进程不会结束。
代码看起来像这样(不是一个非常好的例子,因为ps
不使用stdin
数据,我想:
var Spawn = require("child_process").spawn;
var ps = Spawn("ps");
process.stdin.pipe(ps.stdin);
ps.stdout.pipe(process.stdout);
ps.stderr.pipe(process.stderr);
如果我删除了process.stdin.pipe(ps.stdin)
行,则主要流程结束,但stdin
数据不再用管道传输。
当ps
子进程结束时,为什么主进程没有结束?我该如何解决这个问题?
一个丑陋的解决方案是:
ps.on("close", process.exit.bind(process));
我不喜欢这样,因为我并不想强迫关闭主流程,但我希望自然地关闭 (例如{{1}你等待1000毫秒,然后过程结束)。
答案 0 :(得分:0)
我不知道这是Node中的错误还是预期的行为,但是有两种解决方法,其中一种可能适合您。
如果应该在子进程死亡时准确地终止当前进程,则可以为exit
添加一个处理程序,如下所示:
const fail = err => { throw err }
ps.on("exit", (code, signal) => code !== null ? process.exit(code) : signal !== null ? process.kill(process.pid, signal) : fail("Impossible situation, child process neither exited nor was killed"))
这只会绕过我们的问题,stdin
流坐在那里阻止了一切。
如果您确实需要在当前进程中做更多的事情,而不仅仅是运行该子进程,则此方法可能不可接受。相反,您可以做的是destroy
process.stdin
,恰恰是当您意识到当前流程应该完成的所有工作已经完成时。例如,如果您只想运行ps
,则可以添加:
ps.on("exit", (...) => {
...
process.stdin.destroy()
})
,这将具有相同的效果。如果ps
失效后您需要做更多的工作,则可以将同一件事放入其他合适的事件处理程序中。