如何防止Kill信号在NodeJS子进程的管道流之间传播?

11dmarpk  于 2023-01-30  发布在  Node.js
关注(0)|答案(2)|浏览(132)

问题描述

我有一个由NodeJS派生的子进程,它的输出流(stdout)需要连接到第二个NodeJS子进程输入流(stdin)。
但是,有时候第一个进程会被杀死,在这种情况下,我希望重新启动那个进程,并将其输出流重新连接到***相同的***第二个进程输入,而不必重新启动第二个进程。

首次尝试

我首先尝试连接stdout和stdin,在第一个进程接收到kill信号之前,它们工作正常:

const firstProc = cp.spawn('/some/proc/path', [/* args */])
const secondProc = cp.spawn('/ffmpeg/path', [/* args */])
firstProc.stdout.pipe(secondProc.stdin)

但是,一旦第一个进程接收到删除信号,它就会传播到第二个进程,第二个进程也会终止。
例如,在主NodeJS进程上,我能够拦截SIGINT信号,但这似乎不适用于子进程:

process.on('SIGINT', () => {
  /* do something upon SIGINT kill signal */
})

问题摘要

所以我的问题是:是否有可能在kill信号传输到第二个进程之前拦截子进程上的kill信号,"分离"流连接,启动一个新进程并将其输出管道传输到第二个进程的输入流?

附加注解

我试过在stdout和stdin之间添加一个双工转换流,但似乎没有解决我的问题,因为它在输入关闭时也会关闭。
我考虑过在两个进程之间创建某种套接字连接,但我从未做过类似的事情,我有点担心增加的复杂性。
如果有更简单的方法来处理我的情况,我很高兴知道!谢谢你的任何想法!

wfveoks0

wfveoks01#

请参见www.example.comhttps://nodejs.org/api/stream.html#readablepipedestination-options:
默认情况下,当源Readable流发出'end'时,将对目标Writable流调用stream.end(),因此目标不再可写。若要禁用此默认行为,可以将end选项作为false传递,从而使目标流保持打开状态
所以你要找的是

const secondProc = cp.spawn('/ffmpeg/path', [/* args */]);
function writeForever() {
  const firstProc = cp.spawn('/some/proc/path', [/* args */])
  firstProc.stdout.pipe(secondProc.stdin, { end: false });
  firstProc.stdout.on('end', writeForever); // just spawn a new firstProc and continue…
}
writeForever();
eimct9ow

eimct9ow2#

由于我确实使用了Angular框架,所以我相当习惯于RXJS,这使得这类流任务变得非常容易。
如果您要操作大量的流,我建议将RXJSRXJS-stream一起使用。
生成的代码如下所示:

import { concat, of } from 'rxjs';
import { rxToStream, streamToRx } from 'rxjs-stream';

const concatedStreams$ = concat([
  streamToRx(cp.spawn('/some/proc/path', [/* args */])),
  //of('End of first, start of second'), // Optional
  streamToRx(cp.spawn('/ffmpeg/path', [/* args */])),
]);

rxToStream(concatedStreams$).pipe(process.stdout);

相关问题