18

According to the API docs for Node 0.4.3, the fs.watchFile(filename, [options], listener) function starts a routine that will

Watch for changes on filename. The callback listener will be called each time the file is accessed.

It also says

The options if provided should be an object containing two members a boolean, persistent, and interval, a polling value in milliseconds

Which indicates that it will check every so often based on what is in interval. But it also says

The default is { persistent: true, interval: 0 }.

So does that mean it will check every millisecond to see if the file time changed? Does it listen for OS level events? How does that work?

700 Software
  • 85,281
  • 83
  • 234
  • 341
  • 1
    I think this is a duplicate of http://stackoverflow.com/questions/4482352/node-js-fs-watchfile-persistent-watch-mechanics – Pero P. Mar 22 '11 at 16:43
  • See tjameson's answer: While it may be a duplicate, the answer provided in that old question is outdated. I reckon as of 2013 there are even more modern solutions abound. – Steven Lu Aug 04 '13 at 19:54
  • It's worth noting that in Node v6 the default is `{ persistent: true, interval: 5007 }`. An interval of 0 makes no logical sense. It doesn't look like this was true at the time the question was asked, but [the current implementation in the C source](https://github.com/nodejs/node/blob/db1087c9757c31a82c50a1eba368d8cba95b57d0/deps/uv/src/fs-poll.c#L77) changes 0 to 1: `ctx->interval = interval ? interval : 1;`. – Nateowami Mar 15 '17 at 03:51

2 Answers2

12

Yes, cpedros is correct, this does seem to be a duplicate. I think I can shed some more light on this though.

Each OS has its own file change event that gets fired. On Linux, it is inotify (used to be dnotify), on Mac it is fsevents, and on Windows it is FileSystemWatcher. I'm not sure if the underlying code handles each case, but that's the general Idea.

If you just want to watch a file on Linux, I recommend node-inotify-plus-plus. If you want to watch a directory, use inotify-plus-plus with node-walk. I've implemented this and it worked like a charm.

I can post some code if you're interested. The beauty behind node-inotify-plus-plus is that it abstracts much of the nastiness of inotify and gives an intuitive API for listening to specific events on a file.

EDIT: This shouldn't be used to watch tons of files. On my system, the max is 8192. Your max can be found by using this command cat /proc/sys/fs/inotify/max_user_watches. This could be used to just watch directories for changes and then figure out the individual files from there. A modified event will fire if a file directly under that directory is modified.

EDIT: Thanks @guiomie for pointing out that watching files is now fully supported on Windows. I assume this is with the v0.6.x release.

beatgammit
  • 19,817
  • 19
  • 86
  • 129
  • This is being tested on Cygwin (unix emulator) on Windows, and will ultimately be used in Solaris. – 700 Software Apr 04 '11 at 12:28
  • 1
    Node.js is only supported on Linux I believe, so it's probably doing some kind of polling where inotify isn't supported. – beatgammit Apr 04 '11 at 14:51
  • @tjameson: Do you mean that **file-system listening** is only supported on Linux? [The installation instructions](https://github.com/joyent/node/wiki/Installation) say that *"Node should install out of the box on Linux, Macintosh, and Solaris"*. Which indicates it **is supported** on Mac, Solaris. Perhaps you should **rephrase?** – 700 Software Apr 04 '11 at 16:58
  • Yeah, that's what I meant. I'm not 100% sure about that though. I'd rather use other modules instead because I'm sure NodeJS does something generic with the file listening. That's the only way to be sure. – beatgammit Apr 04 '11 at 17:07
  • 1
    @tjameson You mentioned not to watch tons of files or folders with this. Did you have a method in mind that is more appropriate for watching a large number of files or folders? – funkyeah Apr 06 '11 at 05:17
  • There really isn't a good way. I would keep a db of files, watch directories and then check the mtimes in the db in the directories that change. Kind of a kludge, but it will allow for more watches. The events will fire if any files immediately under the directory have changed. – beatgammit Apr 06 '11 at 06:17
  • @tjameson, thanks for the respone. I would appreciate any code that you post. Also, as a heads-up I have expanded this sub-topic into it's own question and have referenced your comments here. The question is at http://stackoverflow.com/questions/5567457/nodejs-how-would-one-watch-a-large-amount-of-files-folders-on-the-server-side-fo – funkyeah Apr 06 '11 at 14:22
  • 2
    @tjameson File Watch is supported on Windows now. – guiomie Jan 06 '12 at 15:18
  • @tjameson You said that "The events will fire if any files immediately under the directory have changed," but on node 0.6.7 under OS X 10.7, I'm not seeing that behavior -- the event fires on a directory when a file is added or removed, but not when an existing file's mtime or contents changes. Is it possible that this is platform-dependent? – Geoff Jan 20 '12 at 06:31
  • 1
    @tjameson Would you mind posting a small example of how you integrated node-inotify-pluspls with node-walk if you have it available please :) – Carlton Aug 25 '12 at 22:41
  • I'm surprised the native file-events don't bubble to parent directories. – Erik Reppen Apr 04 '13 at 22:13
  • @ErikReppen - At least for Linux, the file-event is just on a file. If the file happens to be a directory, you'll get an event when a file inside the directory changes (no recursion), but for a file, it's just for the file itself. Kinda lame, but it could be very inefficient otherwise. – beatgammit Apr 05 '13 at 08:08
  • @tjameson Well with Linux I guess that effectively is bubbling if you get info about the individual file change in context but I don't know if you get the same details or not from the directory event. Are those directory files just maps basically? – Erik Reppen Apr 05 '13 at 17:41
4

To extend on tjameson's fantastic answer, you could use watchr to normalise the API between the node versiosn and OS watching differences. It also provides events for unlink and new instead of just change, as well as adds support for directory tree watching.

balupton
  • 47,113
  • 32
  • 131
  • 182