Skip to content
Advertisement

Recursively re-spawn file on fsnotify Remove/Rename (Golang)

The Goal:

I am attempting to monitor a file that is subject to being moved or deleted at any time. If and when it is, I’d like to re-generate this file so that an app can continue to write to it.

Attempted:

I have attempted to do this by implementing two functions, monitorFile() to listen for fsnotify events and send the removed filename over a channel to listen() which upon receiving the filepath string over un-buffered channel mvrm (move or rename), will recursively re-generate the file.

Observed behavior:

I can echo 'foo' >> ./inlogs/test.log and see a write notification, and can even rm ./inlogs/test.log (or mv) and see that the file is re-generated… but only once. If I rm or mv the file a second time, the file is not re-generated.

  • Strangely, the undesired behavior does not occur on local Mac OSx (System Version: macOS 10.13.2 (17C88), Kernel Version: Darwin 17.3.0), but does on two different Linux machines with builds:

Linux 3.13.0-32-generic #57-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

Linux 4.9.51-10.52.amzn1.x86_64 #1 SMP x86_64 x86_64 x86_64 GNU/Linux

Diagnostics Attempted:

The differing behavior makes me think I have a race condition. However go build -race provides no output.

I wonder if done chan is receiving due to such a race condition?

Apologies that this is not ‘Playground-able’, but any advice or observation of where this might by racy or buggy would be welcome.

watcher.go:

JavaScript

EDIT:

With some great feedback, I’ve paired this down. In Linux it is now re-generating the file as intended, but after monitoring with top, I see it is spawning a new PID every time the file is moved or deleted, so I do still have a leak. Suggestions as to how I might eliminate this behavior welcome.

https://play.golang.org/p/FrlkktoK2-s

Advertisement

Answer

Please see the code comments, most of the discussion in code comments.

https://play.golang.com/p/qxq58h1nQjp

Outside the golang universe, but facebook has a tool that does pretty much what you are looking for, just not as much go code fun :): https://github.com/facebook/watchman

JavaScript

Have fun!

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement