为啥我通过 spawn() 创建的 Node 子进程挂起?
Posted
技术标签:
【中文标题】为啥我通过 spawn() 创建的 Node 子进程挂起?【英文标题】:Why is my Node child process that I created via spawn() hanging?为什么我通过 spawn() 创建的 Node 子进程挂起? 【发布时间】:2014-01-14 13:23:06 【问题描述】:我正在使用 spawn() 进行 git 调用。有时它可以正常工作,但有时它似乎挂起。我没有看到任何事件触发(错误、退出、关闭),但我看到了该过程确实成功完成的证据。
var spawn = require('child_process').spawn;
spawn('git', ['push', 'origin', 'master'])
.on('error', function(error)
console.log("ERROR: DETAILS: " + error);
)
.on('close', function(code)
console.log("SUCCESS: CODE: " + code);
)
.on('exit', function(code)
console.log("EXIT: CODE: " + code);
)
【问题讨论】:
【参考方案1】:事实证明,一旦 stderr 缓冲区超过 24kb,您必须从中读取,否则您将看不到任何完成事件。可能的解决方法:
在 spawn 调用中设置 stdio 选项。
spawn('git', ['push', 'origin', 'master'], stdio: 'ignore');
请参阅 Node ChildProcess 文档了解所有可能性 - 有很多。
添加一个 on(data) 处理程序。
var git = spawn('git', ['push', 'origin', 'master']);
...
git.stderr.on('data', function(data)
// do something with it
);
通过管道将其传输到标准输出/标准错误。这对您的应用程序来说可能过于冗长,但为了完整性而将其包含在内。
var git = spawn('git', ['push', 'origin', 'master']);
...
git.stderr.pipe(process.stderr);
git.stdout.pipe(process.stdout);
【讨论】:
this Node issue 中包含一个可重现的案例。我相信 exit 不会触发这一事实是一个错误,因为缓冲区的大小会导致不同的行为。 事实证明,这正是使用子进程时的方式。您必须对 stdio 管道做一些事情,否则会冒着子进程挂起的风险,因为它的管道已满。另见this thread。 在这种情况下,孩子没有挂,它已经退出了。但是,节点代码不接收任何事件。我在子进程消失的地方看到了同样的事情,但是节点从不触发退出或关闭事件,并且我的节点代码死锁等待发生的事情不会发生。对我来说,错误是间歇性的,并不是 100% 可靠地重现。以上是关于为啥我通过 spawn() 创建的 Node 子进程挂起?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 Python 多处理中将 start 方法从“fork”更改为“spawn”不再允许我运行我的工作?
为啥我的 iOS 应用无法使用 Node.js Agora Token Server 创建的令牌通过 AgoraRtcEngineKit 进行身份验证?
node js cli STDOUT STDERR 输出 exec 和 spawn 命令