diff --git a/tail.go b/tail.go index c68d7b2..8e8a71a 100644 --- a/tail.go +++ b/tail.go @@ -190,7 +190,7 @@ func (tail *Tail) tailFileSync() { // File got deleted/renamed if tail.ReOpen { // TODO: no logging in a library? - log.Printf("Re-opening moved/deleted file %s ...", tail.Filename) + log.Printf("Re-opening moved/deleted/truncated file %s ...", tail.Filename) err := tail.reopen() if err != nil { tail.close() diff --git a/watch.go b/watch.go index df99e25..cf653d6 100644 --- a/watch.go +++ b/watch.go @@ -24,10 +24,11 @@ type FileWatcher interface { // InotifyFileWatcher uses inotify to monitor file changes. type InotifyFileWatcher struct { Filename string + Size int64 } func NewInotifyFileWatcher(filename string) *InotifyFileWatcher { - fw := &InotifyFileWatcher{filename} + fw := &InotifyFileWatcher{filename, 0} return fw } @@ -65,19 +66,29 @@ func (fw *InotifyFileWatcher) ChangeEvents(_ os.FileInfo) chan bool { ch := make(chan bool) go func() { + defer w.Close() + defer w.RemoveWatch(fw.Filename) + defer close(ch) + for { + prevSize := fw.Size + evt := <-w.Event switch { case evt.IsDelete(): fallthrough case evt.IsRename(): - close(ch) - w.RemoveWatch(fw.Filename) - w.Close() return case evt.IsModify(): + fi, _ := os.Stat(fw.Filename) + fw.Size = fi.Size() + + if prevSize > 0 && prevSize > fw.Size { + return + } + // send only if channel is empty. select { case ch <- true: @@ -93,10 +104,11 @@ func (fw *InotifyFileWatcher) ChangeEvents(_ os.FileInfo) chan bool { // PollingFileWatcher polls the file for changes. type PollingFileWatcher struct { Filename string + Size int64 } func NewPollingFileWatcher(filename string) *PollingFileWatcher { - fw := &PollingFileWatcher{filename} + fw := &PollingFileWatcher{filename, 0} return fw }