rabbitmq 如何在节点js中保持派生的子进程处于活动状态

nwsw7zdq  于 2022-11-08  发布在  RabbitMQ
关注(0)|答案(3)|浏览(128)

我想创建一个rabbitmq cli像foreverjs一样运行。它可以生成child_process并让它在后台运行,并且可以随时与child_process通信。我面临的问题是当主cli程序退出时,child_process似乎也停止运行,我试图用detached:true和.unref()派生它不起作用。即使父调用程序退出后,我如何在后台运行子进程?
cli.js -父级

const { fork, spawn } = require('child_process');
const options = {
  stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
  slient:true,
  detached:true
};

child = fork('./rabbit.js', [], options)

child.on('message', message => {
  console.log('message from child:', message);
  child.send('Hi');
  // exit parent
  process.exit(0);
});

child.unref()

rabbit. js-child如果它已启动并运行,则'i'应保持递增

var i=0;
i++;
if (process.send) {
  process.send("Hello"+i);
}

process.on('message', message => {
  console.log('message from parent:', message);
});
cyvaqqii

cyvaqqii1#

我认为fork没有detached选项。请参阅fork的节点文档。
如果您使用spawn,即使父进程退出,子进程也会继续运行。

客户名称

const { fork, spawn } = require('child_process');
const options = {
  slient:true,
  detached:true,
    stdio: [null, null, null, 'ipc']
};

child = spawn('node', ['rabbit.js'], options);
child.on('message', (data) => {
    console.log(data);
    child.unref();
    process.exit(0);
});

兔子.js

var i=0;
i++;
process.send(i);
// this can be a http server or a connection to rabbitmq queue. Using setInterval for simplicity
setInterval(() => {
    console.log('yash');
}, 1000);

我认为当你使用fork时,一个IPC channel在父进程和子进程之间建立。你可以尝试在退出父进程之前优雅地断开IPC channel。我会尝试一下,如果成功的话,我会更新答案。

更新日期:

我已经更新了cli.jsrabbit.js,使其可以正常工作。诀窍是在stdio选项中使用ipc文件描述符。这样你就可以从子选项与父选项进行通信。如果标记为null,则前三个fd将是默认值。要了解更多信息,请参阅stdio选项文档

xmd2e60i

xmd2e60i2#

一个老问题,但对于那些拿起我今天:fork确实有一个detached选项。但是,它也会打开一个IPC通道,如果您想断开父级和子级之间的关系,也必须使用disconnect()显式关闭该通道。
在我的例子中,在确认子进程已经准备好执行其工作之前使用通道是有利的,然后断开它:

// Run in background
        const handle = cp.fork('./service/app.js', {
          detached: true,
          stdio: 'ignore'
        });
        // Whenever you are ready to stop receiving IPC messages
        // from the child
        handle.unref();
        handle.disconnect();

这允许我的父进程退出,而不杀死后台进程或通过引用它来保持活动状态。
如果您确实建立了handle.on(...)处理程序,那么最好在使用完它们之后将它们与handle.off(...)断开连接。我使用了一个handle.on('message', (data) => { ... })处理程序,以允许子处理程序在完成一些异步启动工作后通知父处理程序何时准备好执行其任务。

pbgvytdp

pbgvytdp3#

fork和spawn都有分离选项。

但是,当父进程退出时,子进程可能希望写入初始标准输出(通过“process.stdout.write”、“console.log”等)。但是,此标准输出可能不再可用(因为父进程已终止),从而在子进程中引发一些异常(例如,管道损坏)。这些异常可能导致子进程也意外失败。
如果我们***允许子程序写入某些始终可用的输出***(例如文件),它将不再失败,因为它仍然可以将信息写入有效实体。

/**
 * This code apart from the comments is available on the Node website
 */

// We use fork, but spawn should also work
const {fork} = require('child_process');

let out = fs.openSync("/path/to/outfile", "a");
let err = fs.openSync("/path/to/errfile", "a");

const child = fork(jsScriptPath, ["--some", "arg"], {
    detached: true,
    stdio: ["pipe", out, err, "ipc"], // => Ask the child to redirect its standard output and error messages to some files
    // silent is overriden by stdio
});

// SetTimeout here is only for illustration. You will want to use more valid code
setTimeout( () => {
    child.unref();
    process.exit(0);
}, 1000);

相关问题