Nodejs监听日志文件的变化的过程解析
最近有在做日志文件的分析,其中有一个需求:A服务器项目需要用Nodejs监听日志文件的变化,当项目产生了新的日志信息,将新的部分通过socket传输到B服务器项目。socket暂时不做分析。
这个需求很简单,通过分析我们开始撸码吧。在撸码的过程中还能巩固所学Nodejs的API,何乐而不为呢?
所用的API
fs.watchFile()
语法
fs.watchFile(filename[,options],listener)
参数解析
filename| | ——文件名 options
监视filename的更改。每当访问文件时都会调用listener回调。
listener有两个参数,当前的stat对象和之前的stat对象
这些stat对象是fs.Stat的实例。
要在修改文件(而不仅仅是访问)时收到通知,则需要比较curr.mtime和prev.mtime。
当fs.watchFile操作导致ENOENT错误时,它将调用一次监听器,并将所有字段置零(或将日期设为Unix纪元)。如果文件是在那之后创建的,则监听器会被再次调用,且带上最新的stat对象。这是v0.10之后的功能变化。
使用fs.watch()比fs.watchFile和fs.unwatchFile更高效。应尽可能使用fs.watch代替fs.watchFile和fs.unwatchFile。
当fs.watchFile()正在监视的文件消失并重新出现时,第二次回调事件(文件重新出现)返回的previousStat会与第一次回调事件(文件消失)返回的previousStat相同。
这种情况发生在:
- 文件被删除,然后又恢复。
- 文件被重命名两次,且第二次重命名回其原来的名称。
例子
fs.watchFile('message.text',(curr,prev)=>{ console.log(`当前的最近修改时间是:${curr.mtime}`); console.log(`之前的最近修改时间是:${prev.mtime}`); });
fs.open()
语法
fs.open(path[,flags[,mode]],callback)
参数解析
path| | ——文件路径 flags | 默认值:'r'。——文件系统标志 mode 默认值:0o666(可读写)。——设置文件模式(权限和粘滞位),但仅限于创建文件的情况 callback err ——错误 fd ——文件系统流
fs.read()
语法
fs.read(fd,buffer,offset,length,position,callback)
参数解析
fd——文件系统流 buffer | | ——数据将写入的缓冲区 offset ——buffer中开始写入的偏移量 length ——要读取的字节数 position ——从文件中开始读取的位置 callback err bytesRead buffer
fs.createReadStream()
语法
fs.createReadStream(path[,options])
参数解析
path| | ——文件路径 options |
返回:
如果autoClose为false,则即使出现错误,也不会关闭文件描述符。应用程序负责关闭它并确保没有文件描述符泄漏。如果autoClose设为true(默认行为),则在'error'或'end'事件时将自动关闭文件描述符。
mode用于设置文件模式(权限和粘滞位),但仅限于创建文件的情况。
例子
读取sample.txt文件的10个字符
fs.createReadStream('sample.txt',{start:90,end:99});
readLine.createInterface
语法
readline.createInterface(options)
参数解析
options
input
要监听的可读流。此选项是必需的。
output将逐行读取数据写入的可写流。
completer用于Tab自动补全的可选函数。
terminal如果input和output应该被视为TTY,并且写入ANSI/VT100转义码,则为true。默认值:实例化时在output流上检查isTTY。
historySize保留的最大历史记录行数。要禁用历史记录,请将此值设置为0。仅当用户或内部output检查将terminal设置为true时,此选项才有意义,否则根本不会初始化历史记录缓存机制。默认值:30。
prompt-要使用的提示字符串。默认值:'>'。
crlfDelay如果\r与\n之间的延迟超过crlfDelay毫秒,则\r和\n将被视为单独的行尾输入。 crlfDelay将被强制转换为不小于100的数字。可以设置为Infinity,这种情况下,\r后跟\n将始终被视为单个换行符(对于使用\r\n行分隔符的文件读取可能是合理的)。默认值:100。
removeHistoryDuplicates如果为true,则当添加到历史列表的新输入行与旧的输入行重复时,将从列表中删除旧行。默认值:false。
escapeCodeTimeoutreadline将会等待一个字符的持续时间(当以毫秒为单位读取模糊键序列时,可以使用输入读取到目前为止形成完整的键序列,并且可以采取额外的输入来完成更长的键序列)。默认值:500。
文件系统标志
这个不需要司机,记住常见的即可,需要的时候查找。
当flag选项采用字符串时,可用以下标志:
'a'-打开文件用于追加。如果文件不存在,则创建该文件。
'ax'-与'a'相似,但如果路径已存在则失败。
'a+'-打开文件用于读取和追加。如果文件不存在,则创建该文件。
'ax+'-与'a+'相似,但如果路径已存在则失败。
'as'-以同步模式打开文件用于追加。如果文件不存在,则创建该文件。
'as+'-以同步模式打开文件用于读取和追加。如果文件不存在,则创建该文件。
'r'-打开文件用于读取。如果文件不存在,则出现异常。
'r+'-打开文件用于读取和写入。如果文件不存在,则出现异常。
'rs+'-以同步模式打开文件用于读取和写入。指示操作系统绕过本地的文件系统缓存。
这对于在NFS挂载上打开文件时非常有用,因为它允许跳过可能过时的本地缓存。它对I/O性能有非常实际的影响,因此除非需要,否则不建议使用此标志。
这不会将fs.open()或fsPromises.open()转换为同步的阻塞调用。如果需要同步的操作,则应使用fs.openSync()之类的。
'w'-打开文件用于写入。如果文件不存在则创建文件,如果文件已存在则截断文件。
'wx'-与'w'相似,但如果路径已存在则失败。
'w+'-打开文件用于读取和写入。如果文件不存在则创建文件,如果文件已存在则截断文件。
'wx+'-与'w+'相似,但如果路径已存在则失败。
fs.Stats类
fs.Stats对象提供有关文件的信息。
Stats{ dev:2114, ino:48064969, mode:33188, nlink:1, uid:85, gid:100, rdev:0, size:527, blksize:4096, blocks:8, atimeMs:1318289051000.1, mtimeMs:1318289051000.1, ctimeMs:1318289051000.1, birthtimeMs:1318289051000.1, atime:Mon,10Oct201123:24:11GMT, mtime:Mon,10Oct201123:24:11GMT,
ctime:Mon,10Oct201123:24:11GMT,
birthtime:Mon,10Oct201123:24:11GMT}
开始监听日志文件
前提,在app.js中调用watchFile方法,将需要监听的文件路径传入该方法中。
functionwatchFile(filename){ console.log('Logmonitoring...'); //Openthefileforreadingandappending fs.open(filename,'a+',function(err,fd){ if(err){ throwerr; } varbuffer; fs.watchFile(filename,{ persistent:true, interval:1000 },(curr,prev)=>{ //Comparethetimebeforeandafter if(curr.mtime>prev.mtime){ //console.log(`Thecurrentlatestrevisiontimeis:${curr.mtime}`); //console.log(`Thelatestmodificationtimeis:${prev.mtime}`); //Changesinthecontentsofdocuments buffer=newBuffer(curr.size-prev.size); //(curr.size-prev.size)thisisthenewlyaddedlengthofthelogfile readFile(fd,buffer,(curr.size-prev.size),prev.size); } }); }); }
读取新增内容
functionreadFile(fd,buffer,length,position){ //readfile fs.read(fd,buffer,0,length,position,function(err,bytesRead,buffer){ if(err){ log.error(err); } console.log('AdditionalContents',buffer.toString()); }); }
额外功能:读取历史内容
functionfetchHistoryLogs(filename){ constrl=readLine.createInterface({ input:fs.createReadStream(filename,{ enconding:'utf8' }), output:null, terminal:false }); rl.on('line',(line)=>{ if(line){ logsArr.push(line.toString()); } }).on('close',()=>{ for(vari=0;i总结
以上所述是小编给大家介绍的Nodejs监听日志文件的变化的过程解析,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。