Search code examples
node.jssocket.ioreadfilewatchtail

tail -f implementation in node.js


I have created an implementation of tail -f in node.js using socket.io and fs.watch function.

I read the file using fs.readFile, convert it into array of lines and returns it to the client. Stores the current length in variable. Then whenever the "file changed" event fires, I re-read the whole file, converts it into array of lines. And then compare the old length and current length. and slice it like

fileContent.slice(oldLength, fileContent.length)

this gives me the changed content. So running perfectly fine.

Problem: I am reading the whole file every time the file gets changed, which is not efficient if file is too large. So is there any way, of reading a file once, and then gets the changed content if there is any change?

I have also tried, spawning child process for "tail -f"

var spawn = require ('child_process').spawn;
var child = spawn ('tail', ['-f', logfile]);
   child.stdout.on ('data', function (data){
   linesArray = data.toString().split("\n")
   console.log ( "Data sent" + linesArray[0]);

   io.emit('changed', {
      data: linesArray,
   });
});

the problem with this is:

  1. on("data") event fires multiple time when I save the logfile by writing some content.
  2. On first load, it correctly returns the last ten line of the file. But if there is a change then it return the whole content again and again.

So if you have any idea of solving this problem let me know. Till then I will dig the internet.


Solution

  • So, I got the solution by reading someone else's code. So solution was to use fs.open which will open the file and then instead of reading whole file we can read the particular block from the file using fs.read() function. To know about the fs.open/fs.read, read this nodejs-file-system.

    Official doc : fs.read