【问题标题】:How to detach a spawned child process in a Node.js script?如何在 Node.js 脚本中分离生成的子进程?
【发布时间】:2012-10-13 09:21:16
【问题描述】:

Intent:使用指定参数调用外部应用程序,并退出脚本。

以下脚本无法正常工作:

 #!/usr/bin/node
 var cp = require('child_process');
 var MANFILE='ALengthyNodeManual.pdf';
 cp.spawn('gnome-open', ['\''+MANFILE+'\''], {detached: true});

尝试过的东西:exec - 没有分离。非常感谢提前

【问题讨论】:

  • 切向:spawn 默认不在 shell 中运行您的命令,因此您不需要在 MANFILE 参数周围加上单引号。

标签: node.js


【解决方案1】:

来自 node.js 文档:

默认情况下,父母会等待分离的孩子退出。要防止父级等待给定的子级,请使用 child.unref() 方法,父级的事件循环不会将子级包含在其引用计数中。

当使用 detached 选项启动一个长时间运行的进程时,该进程将不会在后台保持运行,除非它提供了一个未连接到父级的 stdio 配置。如果继承父级的 stdio,则子级将保持连接到控制终端。

你需要像这样修改你的代码:

#!/usr/bin/node
var fs = require('fs');
var out = fs.openSync('./out.log', 'a');
var err = fs.openSync('./out.log', 'a');

var cp = require('child_process');
var MANFILE='ALengthyNodeManual.pdf';
var child = cp.spawn('gnome-open', [MANFILE], { detached: true, stdio: [ 'ignore', out, err ] });
child.unref();

【讨论】:

  • 可以为stdin、stdout、stderr设置“忽略”:stdio: ['ignore' /* stdin */, 'ignore' /* stdout */, 'ignore' /* stderr */]
  • 确保子进程与父进程解耦的最重要的部分是最后一行child.unref(); 也可以使用stdio: 'ignore' 来静默所有(stdin/stdout/stderr)跨度>
  • 这对于远程反弹服务器很有用:服务器生成一个分离的自身克隆并退出。
  • 嘿 - 我复制粘贴了这个并进行了正确的修改,但它没有按预期工作。我有一个在 docker 容器上运行的服务,它通过一个 API 启动一个负责更新图像的 shell 脚本。尽管 docker 实例被销毁的那一刻,spawn 也死了。有什么建议吗?
【解决方案2】:

我对这个问题的解决方案:

app.js

require('./spawn.js')('node worker.js');

spawn.js

module.exports = function( command ) {
    require('child_process').fork('./spawner.js', [command]); 
};

spawner.js

require('child_process').exec(
    'start cmd.exe @cmd /k "' + process.argv[2] + '"', 
    function(){}
);
process.abort(0);

【讨论】:

  • 尽管您选择了答案,但我还是在此处添加了此内容,因为我的谷歌搜索让我没有明显的替代解决方案。
  • 如您所见,这是特定于操作系统的。对于那些在 OS X 和 Unix/Linux 上的人来说不是很有帮助。接受的答案使用 node.js 自己的标准库。
  • 目的是:创建一个分离的命令终端并传递一个命令,也就是启动一个进程。 'child_process' 遗憾的是,在这方面,从主进程中生成独立进程的需求略显不足。只需替换为您的 Linux 风格:xterm、xdg-open。除非你能告诉我用你的代码做到这一点的方法......然后在 Windows 和 linux 上都可以工作。 ;P 就像我说的那样,我正在尝试解决一个接近但不太接近您想要的位置的问题。谷歌把我扔到这里,作为我放弃并为自己想办法之前的最后希望。很抱歉给您带来麻烦。
  • 我刚刚发现 Web 应用程序的 fork() 将尝试使用父级已使用的相同 IP 地址和端口。所以孩子会报错EADDRINUSE
猜你喜欢
  • 2013-11-04
  • 2013-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2011-08-11
  • 2012-08-07
  • 2015-10-30
相关资源
最近更新 更多