Native file system watcher for Linux

If you’re an IntelliJ user working under Linux you’ve probably seen that boring “Synchronizing files…” spinning icon in a left corner of a status bar. It is there because for an intelligent IDE it is a must to be in the know about any external changes in files it working with – e.g. changes made by VCS, or build tools, or code generators etc. On Windows and Mac OS X native file system watchers used to facilitate this task but on Linux the only option was to recursively scan directory tree. Now you’re welcome to give a try to native file system watcher for Linux.

Prerequisites

File system watcher requires inotify(7) facility. It is in mainstream kernel for more than two years (since 2.6.13, and in glibc since 2.4) so chances are your distribution don’t missing it. The sign of inotify availability in a system is a presence of /proc/sys/fs/inotify/ directory.

Download and setup

File system watcher is a single binary executable (fsnotifier) and can be downloaded directly from our Git repository. It should be named ‘fsnotifier’, placed into bin/ directory of your IDE and granted execution rights. Inotify requires a “watch handle” to be set for each directory it monitors. Unfortunately, the default limit of watch handles may not be enough for reasonably sized projects (e.g. IntelliJ IDEA sources contain 30000+ directories). The current limit can be verified by executing:

cat /proc/sys/fs/inotify/max_user_watches

It can be raised by adding following line to the /etc/sysctl.conf file:

fs.inotify.max_user_watches = 524288

… and issuing this command to apply the change:

sudo sysctl -p

64-bit systems

If your system is strictly 64-bit (i.e. doesn’t contains 32-bit runtime libraries in /lib32 directory) you should download 64-bit version here. Rename downloaded file to “fsnotifier”, rest of setup is same.

This entry was posted in New Features and tagged . Bookmark the permalink.

42 Responses to Native file system watcher for Linux

  1. How do I know if Idea is using fsnotifier ?

  2. Rui Vieira says:

    Great work!

  3. Stefan A. says:

    I’ve build a 64bit version from the sources, seems to work.

  4. trespasserw says:

    @Dragisa You can check idea.log.
    @Stefan It runs in a separate process so there is no need for it to be 64bit.

  5. oleg_s says:

    @Dragisa
    Try using:
    ps axf
    IDEA Java process should have subprocess fsnotifier.

    Regards,
    Oleg

  6. marp says:

    I did exactly what you wrote, downloaded it, placed it in idea’s bin/ dir and gave it +x permissions. But it doesn’t seem to start, ps aux doesn’t show any child processes for idea’s java process, and idea.log says:
    –snip–
    2010-04-16 10:51:58,198 [ 16139] INFO – api.vfs.impl.local.FileWatcher – Native file watcher failed to startup.
    –snip–
    Something’s wrong…

  7. Gleb says:

    Does it work with the latest RubyMine build as well?

  8. Carl Letourneau says:

    I had the right max_user_watches set already, and if I run “ps axf”, I don’t see any subprocess for IntelliJ.

    Carl

  9. William Pietri says:

    Fantastic. It’s great to see you folks paying attention to improving performance like this.

  10. Gus says:

    Awesome! Is this targetted to 9.0.2?

  11. Nick says:

    This is exactly what I need. Unfortunately it is not working.

    I have the lib installed and I’ve ensure the file is executable. The only thing I get in the log is this:

    2010-04-19 10:57:08,338 [ 6781] INFO – api.vfs.impl.local.FileWatcher – Native file watcher failed to startup.

    Any ideas?

  12. WarnerJan says:

    How can I get more information about why it failed?

    2010-04-20 09:18:50,985 [ 10281] INFO – api.vfs.impl.local.FileWatcher – Native file watcher failed to startup.

    Running:
    Linux 2.6.30.10-105.2.23.fc11.x86_64 #1 SMP Thu Feb 11 07:06:34 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux (Fedora 11)

    java version “1.6.0_18″
    Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
    Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)

  13. trespasserw says:

    @marp, @Carl, @Nick, @WarnerJan debugging instructions is here: http://confluence.jetbrains.net/display/~roman.shevchenko/Debugging+native+file+system+watcher+for+Linux

    @Gleb yes, it works with any product based on IntelliJ platform.

    @Gus it should work with previous versions too.

  14. marp says:

    @trespasserw: I followed the debugging instructions, but I don’t get any logging output in any file below /var/log. Even when using level “debug”.

  15. WarnerJan says:

    @trespasserw: +1 for marp’s comment.

  16. trespasserw says:

    Debugging instructions and watcher itself were updated.

  17. Ronnie76er says:

    I don’t know if it matters, but I named the file fsnotifier in the bin directory…not the original name it downloaded as.

    I can see it running as a subprocess…..

  18. Well, I also named the file ‘fsnotifier’ in the bin directory. But like the others, I don’t get an fsnotifier subprocess under neither IDEA 9.0.1 nor 9.0.2

  19. OK, forget my last comment. Thought I had given fsnotifier execute permissions, but that was not the case. After running chmod +x fsnotifier it is started by IDEA.

  20. marp says:

    Great, now I got it working (in IDEA 9.0.2). The key was to rename the downloaded file to “fsnotfier”, otherwise it doesn’t launch.
    @trespasserw: Perhaps you can name the downloaded artifact correctly per default, so the user doesn’t have to rename it.

  21. marp says:

    Regarding my last comment: of course it’s “fsnotifier”…

  22. Hugo Palma says:

    Great work guys, when will this be included in the default product download ?

  23. WarnerJan says:

    Hmm, still no luck. If I run this on the commandline I get:
    [root@pcwj bin]# ./fsnotifier
    bash: ./fsnotifier: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

    Apparently this does not play nice with 64 bit Linux. Any thoughts on how to fix this?

  24. trespasserw says:

    @WarnerJan It should work well. But may be you system misses 32-bit glibc. What do “file ./fsnotifier” and “ldd ./fsnotifier” say?

  25. WarnerJan says:

    [root@pcwj bin]# ./fsnotifier
    bash: ./fsnotifier: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
    [root@pcwj bin]# ldd fsnotifier
    not a dynamic executable

  26. trespasserw says:

    @WarnerJan I’ve updated the post to include link on a 64-bit version.

  27. jeanpaul says:

    The fsnotifier –selftest says that my home directory is unwatchable. Why ?

  28. WarnerJan says:

    Sorry, been on holiday for a while… Just notifiying (no pun intended :)) that it works.
    Thanks a lot!

    5649 2010-05-12 16:27:52,196 [ 2602] INFO – api.vfs.impl.local.FileWatcher – Native file watcher is operational.

  29. trespasserw says:

    @Hugo (sorry for the late answer) when it will be considered stable enough

    @jeanpaul if there are not enough watch descriptors for a tree behind it, or if it is on network file system – it is hard to guess without full self-test log

  30. jeanpaul says:

    My files are located on a network file system. :( Is this a limitation in inotify?

  31. trespasserw says:

    @jeanpaul
    It is. Network file systems don’t produce file change notifications. May be not all but at least all of those in wide use.

  32. jeanpaul says:

    Too bad. It takes “forever” for IDEA to check all files for changes before running my application.

  33. trespasserw says:

    @jeanpaul
    You can disable automatic synchronization (File | Settings | General).

  34. Ray says:

    I am having an odd situation with fsnotifier, here is my scenario:
    my source code is located on an SSD HardDrive formatted using ext3 filesystem
    my IntelliJ9.0.2 is running on another harddrive alongside my operating system also formatted to ext3
    I am using subversion as my VCS and when I run an update from the command line, it doesn’t update the file contents inside of intelliJ. Instead it puts a little yellow bar at the top of the file that says “Outdated version… Show Diff | Update Project”
    Then when I try to make changes to the file, it comes up with an alert stating the the file system version is different than the version in memory, do I want to load the FS version or keep the memory version.

    My question is: Why are these files not automatically updating in IntelliJ when I do the update from the command line.

    I checked if the fsnotifier was running and it is. I also did the test on fsnotifier to see if it was running correctly and it is as well.

    Any suggestion?

  35. Ray says:

    Also to note, that when I click on the ‘Update Project’ link from the yellow bar at the top of the file, it sits for a while, svn updating the already updated projects, then after its done, the file STILL doesnt have the changes from the file system.

    The only method I found that works is to close and reopen intelliJ

  36. trespasserw says:

    @Ray please run a short session with fsnotifier log level set to DEBUG and then attach a log to the abovementioned page.

  37. trespasserw says:

    @Ray I’m sorry but it’s impossible to say what’s wrong from short log. Can you please make a log with the level set to DEBUG?

  38. Mark says:

    Hi trespasserw, this sounds ilke a great feature, but I’ve tried it a few times, and it just doesn’t want to play ball.

    Does it only watch the content roots of my project, or everything it can find under some location, such as where my project files are? The log below suggests it might be the latter, which is a problem – I have many Gbytes of stuff under there it should not look at. Shouldn’t it strictly look only at my content roots?

    Also, how do I know if it’s working? It is running, but when I edit a file by hand it does not update in the IDE as expected. I have synchronization set to manual in the IDE – do I have to change that setting?

    If I run it at INFO level, I see this in the log: Should I see something at INFO level when I edit a file? I don’t see anything. Also, there’s no mention in the log of any of my content roots, though the proj dir sits above them. Should I see the content roots listed here?

    Repeated messages about dirs I don’t care about, eg,
    Jul 30 23:41:57 marsbar fsnotifier[1082]: unwatchable: /proc
    Jul 30 23:41:57 marsbar fsnotifier[1082]: unwatchable: /sys
    Jul 30 23:41:57 marsbar fsnotifier[1082]: unwatchable: /sys/fs/fuse/connections

    Strange sequences like this:

    Jul 30 23:42:06 marsbar fsnotifier[1082]: unregistering root: /tmpfs/intellij9/system
    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /tmpfs/intellij9/system
    (IntelliJ sys dir – why does it even look here?)

    Registration of some of my library classes like this:

    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /usr/local/mwr/intellic-cache/marsbar/libs/mylib/classes

    Then it unregisters the same thing:

    Jul 30 23:42:06 marsbar fsnotifier[1082]: updating roots (curr:2, new:6)
    Jul 30 23:42:06 marsbar fsnotifier[1082]: unregistering root: /usr/local/mwr/intellic-cache/marsbar/libs/mylib/classes (library classes)

    More stuff that looks weird, again, why is it looking at system dir?:

    Jul 30 23:42:06 marsbar fsnotifier[1082]: unregistering root: /tmpfs/intellij9/system
    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /tmpfs/intellij9/system

    My project dir, where the project files are:

    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /usr/local/mwr/myproj

    Intellij’s own build output location (why?):

    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /usr/local/mwr/intellic-cache/marsbar/intellij_classes

    My libs again:
    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /usr/local/mwr/intellic-cache/marsbar/libs/mylib/src

    JDK
    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /opt/jdk1.6.0_20_32bit

    More apparent redundancy:
    Jul 30 23:42:06 marsbar fsnotifier[1082]: registering root: /usr/local/mwr/intellic-cache/marsbar/libs/mylib/classes

    And a whole lot more stuff I shouldn’t care about:

    Jul 30 23:42:06 marsbar fsnotifier[1082]: unwatchable: /proc
    Jul 30 23:42:06 marsbar fsnotifier[1082]: unwatchable: /sys
    Jul 30 23:42:06 marsbar fsnotifier[1082]: unwatchable: /sys/fs/fuse/connections
    Jul 30 23:42:06 marsbar fsnotifier[1082]: unwatchable: /sys/kernel/debug
    Jul 30 23:42:06 marsbar fsnotifier[1082]: unwatchable: /sys/kernel/security
    etc…

  39. trespasserw says:

    @Mark
    Yes, you have to enable “Synchronize files on frame activation” option.
    You’ve seen all that messages in log – it means the thing is working. In order to be absolutely sure you can just repeat quick test with editing file outside IDEA.
    File modification events are only reported at DEBUG level.
    IDEA keeps lots of important stuff in it’s system dir and wants to be sure noone touched it. As for external (outside of project root) libs and JDK – one can upgrade any of this externally and IDEA should be aware of changes to provide e.g. correct completion.
    Unwatchable dirs are usually mount points for special and network file systems which don’t generate file modification events.
    Registering/unregistering sequence is a sign of suboptimal algorithm, have to do some optimization.

  40. Mark says:

    Confirmed – it works with sync on frame activation. But we already had that option, so what does this buy us? Is it just faster/more efficient to detect changed files? The biggest cost I notice is indexing, but every little bit helps, for sure.
    Thanks for the great answer, much appreciated.

  41. trespasserw says:

    @Mark
    It is faster, especially on big projects. Without native file watcher IDEA deep scans directory tree when looking for changes.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">