使用Node.js从“命名管道”/ fifo读取

9

我有这个:

  const p = path.resolve(projectRoot + '/NAMEDPIPEIN');
  const fd = fs.openSync(p, 'r+');

  fs.createReadStream(null, {fd}).on('data', function (d) {
    if (String(d).trim() === '[stdin end]') {
      return process.nextTick(cb);
    }
    process.argv.push(String(d).trim());
  });

我启动了Node.js进程,稍后我会写入命名管道。出于某种原因,在数据回调函数中没有接收到任何数据。

我是这样写入命名管道的:

 mkfifo NAMEDPIPEIN
 echo "foo bar baz" > NAMEDPIPEIN

你尝试过在Linux上这个建议了吗? - mscdex
谢谢,我现在正在尝试...不知道它是否适用于Mac。 - Alexander Mills
1
根据那个线程,它(很可能)只能在Linux上运行。 - mscdex
你的代码在我的 Mac 上运行得非常好(每当我向命名管道写入一些数据时,“data”事件就会触发)。顺便说一句,child_process.spawn() 不是解决你正在尝试做的事情的方法吗? - robertklep
在我的情况下,我有一个守护进程。我需要向守护进程发送一些命令。据我所知,在macOS和Linux上进行IPC的最简单方法似乎是使用命名管道。不过,我发现很难弄清楚如何实现。 - Alexander Mills
@mscdex,你分享的例子确实有效,我试过了。使用 net.Socket。 - Alexander Mills
2个回答

10

另一个解决方案来自@richardpringle,但功能有限。

如果您尝试以这种方式打开多个FIFO(线程池中的线程数超过多个),则先打开的那些将不再流式传输数据。 这是因为fs模块不是设计用于在非阻塞模式下使用文件描述符。 相反,请使用net模块!

https://dev59.com/Ca7la4cB1Zd3GeqPjc8N#52622722了解到,目前从FIFO进行流式处理的方法是使用套接字:

const fs = require('fs');
const net = require('net');

fs.open('path/to/fifo/', fs.constants.O_RDONLY | fs.constants.O_NONBLOCK, (err, fd) => {
  // Handle err
  const pipe = new net.Socket({ fd });
  // Now `pipe` is a stream that can be used for reading from the FIFO.
  pipe.on('data', (data) => {
    // process data ...
  });
});

总之,如果您正在运行脚本并且不介意占用线程池中的一个线程,可以使用 @richardpringle 的解决方案。否则,您应该绝对使用此解决方案。


你可以使用O_RDWR和openSync创建一个快速同步函数来替换fs.create*Stream。 - fuzzyTew

3
这应该可以解决问题:
const fs = require('fs');
const path = require('path');

const fifoPath = path.resolve(projectRoot, '/NAMEDPIPEIN')

const fifo = fs.createReadStream(fifoPath);

fifo.on('data', data => {
  // process data...
});

使用fifo.on('data', console.log)进行测试。


1
我还建议使用 fifo.setEncoding('utf8') 设置文件流编码。 - richardpringle
3
如果您向命名管道写入一次,似乎在此之后它就停止工作了。 - user5047085
看看 @Sami 的答案,它更加健壮! - richardpringle
由于您只是使用.on('data'),如果我使用.pipe(),它也会起作用吗? - J-Cake
1
是的,它会,因为它只是一个ReadableStream实例。 - richardpringle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接