Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read from a 'named pipe' / fifo with Node.js

I have this:

  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());
  });

I start the Node.js process, and then later, I write to the named pipe. For some reason no data seems to be arriving in the on data callback.

I am writing to named pipe like so:

 mkfifo NAMEDPIPEIN
 echo "foo bar baz" > NAMEDPIPEIN
like image 995
Alexander Mills Avatar asked Jul 08 '17 04:07

Alexander Mills


2 Answers

The other solution, from @richardpringle should work, but is limited in functionality.

If you try to open multiple FIFOs that way (more than the number of threads in the thread-pool), the first ones you opened won't be streaming data anymore. This is because the fs module isn't designed to work with file-descriptors in non-blocking mode. Instead, use the net module!

From https://stackoverflow.com/a/52622722/1843507 the current way to achieve streaming from a FIFO is using a socket:

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 ...
  });
});

In summary, you can use @richardpringle's solution if you are running a script and don't mind tying up one of the threads in the thread-pool. Otherwise, you should definitely use this solution.

like image 85
Sami Avatar answered Oct 13 '22 00:10

Sami


This should do it:

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...
});

Use fifo.on('data', console.log) for testing.

like image 29
richardpringle Avatar answered Oct 13 '22 01:10

richardpringle