2018-5-21 19:06:48|circuit board 2018-5-21 10:11:22|dash button 2018-5-20 11:46:54|web
$ npm init -y
package.json
file for the Node.js project.package.json
as a dependency: $ npm install --save log-timestamp
log-timestamp
package allows you to attach a time stamp to messages that are output to the console using the console.log
command. This will allow you to analyze the time of occurrence of events related to the monitoring of files. This package is needed solely for training purposes, and, for example, if you will be preparing something similar to what we are going to talk about, for use in production, you will not need to log-timestamp
.fs.watchFile
. const fs = require('fs'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); fs.watchFile(buttonPressesLogFile, (curr, prev) => { console.log(`${buttonPressesLogFile} file Changed`); });
button-pressed.log
. Callback is called after the file is changed.fs.stats
type. This is an object with data about the current state of the file ( curr
), and an object with data about its previous state ( prev
). This allows, for example, to find out the time of the previous file modification using the prev.mtime
construct.button-pressed.log
and make changes to it, the program will respond to this, the corresponding entry will appear in the console. $ node file-watcher.js [2018-05-21T00:54:55.885Z] Watching for file changes on ./button-presses.log [2018-05-21T00:55:04.731Z] ./button-presses.log file Changed
fs.watchFile
method, by default, polls files for changes every 5.007 seconds. This time can be changed by passing fs.watchFile
object with parameters containing the interval
property to the fs.watchFile
method: fs.watchFile(buttonPressesLogFile, { interval: 1000 }, (curr, prev) => { console.log(`${buttonPressesLogFile} file Changed`); });
fs.watchFile
spends system resources on polling files, fs.watch
relies on the operating system for system notifications of file system changes. The documentation says that Node uses the inotify
mechanism in the Linux OS, FSEvents
on MacOS, and ReadDirectoryChangesW
on Windows to receive asynchronous notifications when files change (compare this with synchronous polling of files). The performance gain derived from using fs.watch
instead of fs.watchFile
is even more significant when, for example, you need to keep track of all files in a certain directory, since you can pass either the path to the specific file as the first argument to fs.watch
file or folder. fs.watch
. const fs = require('fs'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); fs.watch(buttonPressesLogFile, (event, filename) => { if (filename) { console.log(`${filename} file Changed`); } });
$ node file-watcher.js [2018-05-21T00:55:52.588Z] Watching for file changes on ./button-presses.log [2018-05-21T00:56:00.773Z] button-presses.log file Changed [2018-05-21T00:56:00.793Z] button-presses.log file Changed [2018-05-21T00:56:00.802Z] button-presses.log file Changed [2018-05-21T00:56:00.813Z] button-presses.log file Changed
fs.watch
. This method allows you to respond to events that occur either when a file is renamed (these are rename
events) or when its content changes. If we need accuracy and we only want to observe changes in the contents of the file, the code should be brought to the following state: const fs = require('fs'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); fs.watch(buttonPressesLogFile, (event, filename) => { if (filename && event ==='change') { console.log(`${filename} file Changed`); } });
rename
event could be detected when running Node under Windows, but not under Raspbian.fs.watch
code by observing the moment of file modification, which will allow us to identify real changes and avoid false positives of the handler. const fs = require('fs'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); let previousMTime = new Date(0); fs.watch(buttonPressesLogFile, (event, filename) => { if (filename) { const stats = fs.statSync(filename); if (stats.mtime.valueOf() === previousMTime.valueOf()) { return; } previousMTime = stats.mtime; console.log(`${filename} file Changed`); } });
previousMTime
variable the value of the previous file modification moment and call console.log
only in cases when the file modification time changes. It seems that this idea is good and now everything should work as we need. Check it out. $ node file-watcher.js [2018-05-21T00:56:50.167Z] Watching for file changes on ./button-presses.log [2018-05-21T00:56:55.611Z] button-presses.log file Changed [2018-05-21T00:56:55.629Z] button-presses.log file Changed [2018-05-21T00:56:55.645Z] button-presses.log file Changed
fs.watch
responds fs.watch
, we calculate the checksum again. We may be able to get rid of unnecessary messages about changing the file, if we take into account the state of the contents of the file. $ npm install --save md5
const fs = require('fs'); const md5 = require('md5'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); let md5Previous = null; fs.watch(buttonPressesLogFile, (event, filename) => { if (filename) { const md5Current = md5(fs.readFileSync(buttonPressesLogFile)); if (md5Current === md5Previous) { return; } md5Previous = md5Current; console.log(`${filename} file Changed`); } });
$ node file-watcher.js [2018-05-21T00:56:50.167Z] Watching for file changes on ./button-presses.log [2018-05-21T00:59:00.924Z] button-presses.log file Changed [2018-05-21T00:59:00.936Z] button-presses.log file Changed
fs.watch
, but never achieved what we wanted. However, not everything is so bad, because, in the search for a solution, we learned a lot of useful information. Let's make another attempt to achieve the desired. At this time, we use the technology to eliminate the “chatter” of events by entering into our code a small delay, which will allow us not to react to events about file changes within the specified time window. const fs = require('fs'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); let fsWait = false; fs.watch(buttonPressesLogFile, (event, filename) => { if (filename) { if (fsWait) return; fsWait = setTimeout(() => { fsWait = false; }, 100); console.log(`${filename} file Changed`); } });
$ node file-watcher.js [2018-05-21T00:56:50.167Z] Watching for file changes on ./button-presses.log [2018-05-21T01:00:22.904Z] button-presses.log file Changed
const fs = require('fs'); const md5 = require('md5'); require('log-timestamp'); const buttonPressesLogFile = './button-presses.log'; console.log(`Watching for file changes on ${buttonPressesLogFile}`); let md5Previous = null; let fsWait = false; fs.watch(buttonPressesLogFile, (event, filename) => { if (filename) { if (fsWait) return; fsWait = setTimeout(() => { fsWait = false; }, 100); const md5Current = md5(fs.readFileSync(buttonPressesLogFile)); if (md5Current === md5Previous) { return; } md5Previous = md5Current; console.log(`${filename} file Changed`); } });
fs.watchFile
to monitor files fs.watchFile
not recommended, since this command, in order to detect file change events, performs regular queries to the system. Instead, pay attention to fs.watch
with a function to suppress the "bounce" of events.Source: https://habr.com/ru/post/360495/
All Articles