mirror of
https://github.com/samsonjs/batteries.git
synced 2026-03-25 09:15:46 +00:00
add FileFollower for tail -f functionality
This commit is contained in:
parent
5295fe8f20
commit
1652d2a782
2 changed files with 88 additions and 4 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
, ArrayExt = require('./array-ext')
|
, ArrayExt = require('./array-ext')
|
||||||
|
, FileFollower = require('./file-follower')
|
||||||
, LineEmitter = require('./line-emitter')
|
, LineEmitter = require('./line-emitter')
|
||||||
, ObjectExt = require('./object-ext')
|
, ObjectExt = require('./object-ext')
|
||||||
, constants = require('constants')
|
, constants = require('constants')
|
||||||
|
|
@ -12,6 +13,7 @@ var fs = require('fs')
|
||||||
FileExt =
|
FileExt =
|
||||||
{ eachLine: eachLine
|
{ eachLine: eachLine
|
||||||
, exists: exists
|
, exists: exists
|
||||||
|
, follow: follow
|
||||||
, grep: grep
|
, grep: grep
|
||||||
, home: home
|
, home: home
|
||||||
, readLines: readLines
|
, readLines: readLines
|
||||||
|
|
@ -58,14 +60,22 @@ function eachLine(f, optionsOrLineFn, endFn) {
|
||||||
|
|
||||||
function exists(f) {
|
function exists(f) {
|
||||||
try {
|
try {
|
||||||
fs.statSync(f)
|
fs.statSync(f);
|
||||||
return true
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.errno === constants.ENOENT) return false
|
if (e.errno === constants.ENOENT) return false;
|
||||||
throw e
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function follow(f, lineFn) {
|
||||||
|
var ff = new FileFollower(f);
|
||||||
|
ff.on('line', lineFn);
|
||||||
|
return {
|
||||||
|
stop: ff.stopFollowing.bind(ff)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function grep(regex, f, callback) {
|
function grep(regex, f, callback) {
|
||||||
if (!callback) throw new Error('grep requires a callback');
|
if (!callback) throw new Error('grep requires a callback');
|
||||||
var results = [];
|
var results = [];
|
||||||
|
|
|
||||||
74
lib/file-follower.js
Normal file
74
lib/file-follower.js
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
// batteries
|
||||||
|
// Copyright 2010 - 2011 Sami Samhuri <sami@samhuri.net>
|
||||||
|
|
||||||
|
var fs = require('fs')
|
||||||
|
, util = require('util')
|
||||||
|
, EventEmitter = require('events').EventEmitter
|
||||||
|
, FileExt = require('./file-ext')
|
||||||
|
;
|
||||||
|
|
||||||
|
module.exports = FileFollower;
|
||||||
|
|
||||||
|
// TODO: option to act like tail and only show the last N lines, N >= 0
|
||||||
|
function FileFollower(file, options) {
|
||||||
|
options = options || {};
|
||||||
|
var self = this;
|
||||||
|
this.file = file;
|
||||||
|
this.currSize = fs.statSync(file).size;
|
||||||
|
this.prevSize = this.currSize;
|
||||||
|
this.interval = options.interval || 1000;
|
||||||
|
FileExt.eachLine(file,
|
||||||
|
{ line: function(line) {
|
||||||
|
self.emit('line', line);
|
||||||
|
}
|
||||||
|
, end: function() {
|
||||||
|
self.startFollowing();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
util.inherits(FileFollower, EventEmitter);
|
||||||
|
|
||||||
|
FileFollower.prototype.startFollowing = function() {
|
||||||
|
if (this._interval) {
|
||||||
|
console.warn('already following');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.buffer = '';
|
||||||
|
this.fd = fs.openSync(this.file, 'r');
|
||||||
|
this._interval = setInterval(this.checkForLine.bind(this), this.interval);
|
||||||
|
};
|
||||||
|
|
||||||
|
FileFollower.prototype.stopFollowing = function() {
|
||||||
|
if (!this._interval) {
|
||||||
|
console.warn('not following');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete this.buffer;
|
||||||
|
clearInterval(this._interval);
|
||||||
|
delete this._interval;
|
||||||
|
fs.closeSync(this.fd);
|
||||||
|
delete this.fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
FileFollower.prototype.checkForLine = function() {
|
||||||
|
this.currSize = fs.statSync(this.file).size;
|
||||||
|
if (this.currSize > this.prevSize) {
|
||||||
|
var n = this.currSize - this.prevSize
|
||||||
|
, buf = new Buffer(n + 1)
|
||||||
|
, self = this
|
||||||
|
;
|
||||||
|
fs.read(this.fd, buf, 0, n, this.prevSize, function(err, bytesRead, buffer) {
|
||||||
|
if (err) {
|
||||||
|
self.emit('error', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.buffer += buf.slice(0, bytesRead);
|
||||||
|
self.prevSize += bytesRead;
|
||||||
|
var i;
|
||||||
|
while ((i = self.buffer.indexOf('\n')) !== -1) {
|
||||||
|
self.emit('line', self.buffer.slice(0, i));
|
||||||
|
self.buffer = self.buffer.slice(i + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue