Golang replaces a previously opened file when creating a new file

Ok, so I control a specific file and do some analysis of the -f tail of this file. However, another application has a certain logic and will create a new file on the next date or even earlier.

I am looking for a way to detect a newly created file (the host is a Linux machine), and then without restarting my current service, to start the tail of the newly created file.

Here is my current logic for the "current file":

func main(){ currentTime := time.Now().Local() currentFileName := strings.Replace(currentTime.Format("2006-01-02"), "-","",2) newFileName := currentFileName + "_1111.log.txt" //using github.com/hpcloud/tail for tail t, err := tail.TailFile("/var/log/"+newFileName, tail.Config{Follow: true, ReOpen: true}) for line := range t.Lines { //fmt.Println("Line is:", line.Text) //check do we have error inside new line if strings.Contains(strings.ToLower(line.Text), "mfc"){ fmt.Println("MFC located: ", line.Text) //now send e-mail to all interested parties //sendEmail(line.Text) } } fmt.Println(err) } 

Well, the current file instead of 20161219_1111.log can be 20161219_2222.log or similar, and the next day it starts with 20161220_1111.log, etc.

Any hints are welcome.

+6
source share
2 answers

try github.com/fsnotify/fsnotify

simple example:

 func newFileCheck() (newFilename chan string, err error) { watcher, err := fsnotify.NewWatcher() if err != nil { // do some log return } err = watcher.Watch("testDir") if err != nil { // do some log return } newFilename = make(chan string) // Process events go func() { for { select { case ev := <-watcher.Event: log.Println("event:", ev) newFilename <- ev.Name // Relative path to the file case err := <-watcher.Error: log.Println("error:", err) } } }() return } func yourApp() { newFilenameChan, err := newFileCheck() if err != nil { // err check } go func() { for { select { case name := <-newFilenameChan: // close the old one and read new file } } }() } 

more details see document

+3
source

Consider the following as a hacked example.

I am not sure if tail.Tail closed tail.Tail if you call Stop or StopAtEOF and then Cleanup .

It is also necessary to clarify aspects of concurrency. Gorutins should be gracefully closed.

Import:

  • github.com/fsnotify/fsnotify
  • github.com/hpcloud/tail

The function of checking new files:

 func newFileCheck(dir string) (newFileAlert <-chan string, err error) { watcher, err := fsnotify.NewWatcher() if err != nil { return } err = watcher.Add(dir) if err != nil { return } newFileAlertSender := make(chan string) newFileAlert = newFileAlertSender go func() { for { select { case ev.Op := <-watcher.Events: log.Println("Event : ", ev) if ev == fsnotify.Create { newFileAlertSender <- ev.Name } case err := <-watcher.Errors: log.Println("Watcher Error : ", err) } } }() return } 

Function for tail file:

 func tailFile(dir, newFileName string, cfg tail.Config, stop <-chan struct{}) { t, err := tail.TailFile(dir+newFileName, cfg) if err != nil { log.Fatalln("TailFile failed - ", err) } for line := range t.Lines { if strings.Contains(strings.ToLower(line.Text), "mfc") { fmt.Println("MFC located: ", line.Text) //sendEmail(line.Text) } select { case <-stop: t.StopAtEOF() default: } } t.Cleanup() } 

The main:

 func main() { dir := "/var/log/" currentTime := time.Now().Local() currentFileName := currentTime.Format("20060102") newFileName := currentFileName + "_1111.log.txt" newFileAlert, err := newFileCheck(dir) if err != nil { log.Fatalln("File watching failed - ", err) } stop := make(chan struct{}) cfg := tail.Config{Follow: true, ReOpen: true} go tailFile(dir, newFileName, cfg, stop) for fileName := range newFileAlert { stop <- struct{}{} go tailFile(dir, fileName, cfg, stop) } } 
+1
source

Source: https://habr.com/ru/post/1013293/


All Articles