Last Updated: February 25, 2016
·
4.093K
· goliardico

"tail -f *" in node.js

Hi,
this's my first experiment with node.js.

fs.watch waits on changes in dir/* files and prints out only new data (as "tail -f" already do).
Just a brief explanation, then the code.

The main loop is:

allFiles.forEach (function (file) {

where I get a list of every file (exit if there's a subdirectory), then save the actual size (in bytes) of file in fNameStat.size and start fs.watch to append on file changes:

fs.watch(fName, function (event, filename) {

When someone modifies a watched file, calculates different size in newDataLenght and create a Buffer to handle it:

var buffer = new Buffer(newDataLength, 'utf-8');

Finally, write to console only changes and save the new size of file:

   console.log(newData.toString());

});
fNameStat = fs.statSync(fName);

This's the complete code. To test it make a directory (and put the path in dir var) with some text files in, run node and make some changes on files from another shell. You'll see changes in realtime from running node's shell.

var fs = require('fs');
var dir = "/var/log/remote";

var allFiles = fs.readdirSync(dir);

allFiles.forEach (function (file) {
  var fName = dir + "/" + file;
  var fNameStat = new Object;

  fNameStat = fs.statSync(fName);

  if (!fNameStat.isFile()) {
    console.log(fName + ' is not a file');
    process.exit(1);
  }

  console.log('watching ' + fName + ' bytes: ' + fNameStat.size);

  fs.watch(fName, function (event, filename) {
    var fNameStatChanged = fs.statSync(fName);
    console.log('file changed from ' + fNameStat.size + ' to ' + fNameStatChanged.size);

    fs.open(fName, 'r', function(err, fd) {
      var newDataLength = fNameStatChanged.size - fNameStat.size;
      var buffer = new Buffer(newDataLength, 'utf-8');
      fs.read(fd, buffer, 0, newDataLength, fNameStat.size, function (err, bytesRead, newData) {
         if (err) {
            console.log(err);
         };
         console.log(newData.toString());

      });
      fNameStat = fs.statSync(fName);
    });

  }); // fs.watch

}); // allFiles.forEach

See:

  1. Node.js docs: Buffer

  2. Node.js docs: fs.watch