@@ -11,7 +11,7 @@ import (
1111
1212 "github.com/nxadm/tail/util"
1313
14- "github.com/fsnotify/fsnotify"
14+ "github.com/fsnotify/fsnotify"
1515 "gopkg.in/tomb.v1"
1616)
1717
@@ -79,6 +79,13 @@ func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChange
7979
8080 events := Events (fw .Filename )
8181
82+ // Check to see the file hasn't been modified already before the watcher started
83+ fi , deleted := fw .checkAndNotifyIfModifiedInBetween (changes )
84+ if deleted {
85+ return
86+ }
87+ fw .Size = fi .Size ()
88+
8289 for {
8390 prevSize := fw .Size
8491
@@ -134,3 +141,28 @@ func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChange
134141
135142 return changes , nil
136143}
144+
145+ func (fw * InotifyFileWatcher ) checkAndNotifyIfModifiedInBetween (changes * FileChanges ) (os.FileInfo , bool ) {
146+ fi , err := os .Stat (fw .Filename )
147+ if err != nil {
148+ if ! os .IsNotExist (err ) {
149+ util .Error ("Failed to stat file %v: %v" , fw .Filename , err )
150+ // Treat it as a deleted file as we cannot read it anyway.
151+ }
152+ _ = RemoveWatch (fw .Filename )
153+ changes .NotifyDeleted ()
154+ return nil , true
155+ }
156+
157+ if fw .Size > fi .Size () { // old file size was larger than now => truncated
158+ changes .NotifyTruncated ()
159+ } else if fw .Size != fi .Size () {
160+ changes .NotifyModified ()
161+ }
162+ // there is a corner case of file that was truncated and replaced with exact same amount of bytes, which would
163+ // result in no notification. However any subsequent writes will capture that
164+ // If the file isn't expected to be written to often and those events cannot be missed, recommend using Polling watcher
165+ // instead of inotify
166+
167+ return fi , false
168+ }
0 commit comments