Gotchas Using fs.watch
with Vim
I was debugging an issue with fs.watch
Node.js file watcher I was using. I
noticed that when the file was edited using Vim, the file watcher could only
detect the intial file change and subsequent file changes would not be detected.
However when editing using another editor like VSCode, the file changes would be
detected.
fs.watch
uses inotify
in Linux. So to debug this I used the inotifywait
command to see what events were being emitted for this file:
jkim@dev-jkim code $ inotifywait --monitor test.txt
Setting up watches.
Watches established.
# First edit
test.txt MOVE_SELF
test.txt ATTRIB
test.txt DELETE_SELF
# Second edit (no output)
For some reason, in the initial edit the file was being deleted. After doing some quick Google searches of 'inotify' and 'vim' I figured out that Vim does the following when you edit a file:
- It would move the file
test.txt
to atest.txt~
presumably for a backup. - It would write the new contents to a new file
test.txt
.
So this explains why we see MOVE_SELF
and DELETE_SELF
events and why
inotify
is unable to see anymore file changes.
It turns out, you can change the behaviour of Vim so that it doesn't create new
files for each edit. You can enable the backupcopy
setting which forces Vim to
overwrite the original file after it makes a copy instead of copying the
original file and creating a new file:
set backupcopy=yes
After I set this, the inotify
behaves as expected
jkim@dev-jkim code $ inotifywait --monitor test.txt
Setting up watches.
Watches established.
# First edit
test.txt OPEN
test.txt ACCESS
test.txt CLOSE_NOWRITE,CLOSE
test.txt OPEN
test.txt MODIFY
test.txt MODIFY
test.txt ATTRIB
test.txt CLOSE_WRITE,CLOSE
test.txt OPEN
test.txt CLOSE_NOWRITE,CLOSE
# Second edit
test.txt OPEN
test.txt ACCESS
test.txt CLOSE_NOWRITE,CLOSE
test.txt OPEN
test.txt MODIFY
test.txt MODIFY
test.txt ATTRIB
test.txt CLOSE_WRITE,CLOSE
test.txt OPEN
test.txt CLOSE_NOWRITE,CLOSE
It's interesting to note that the problem seems to only occur in non-Unix
environments. The help docs for backupcopy
state:
'backupcopy' 'bkc' string (Vi default for Unix: "yes", otherwise: "auto")