在创建新文件时,Golang会替换以前打开的文件

时间:2016-12-19 15:18:33

标签: go

好的,我正在监视某个文件并对该文件进行一些tail -f分析。 但是,另一个应用程序具有特定的逻辑,它将在下一个日期甚至之前创建一个新文件。

我正在寻找一种方法来检测新创建的文件(主机是linux机器),然后不重新启动我当前的go服务以开始拖尾新创建的文件。

这是我当前拖尾“当前文件”的逻辑:

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)
}

当前文件而不是20161219_1111.log可以是20161219_2222.log或类似,第二天它从20161220_1111.log等开始。

欢迎任何提示。

2 个答案:

答案 0 :(得分:3)

尝试使用github.com/fsnotify/fsnotify

一个简单的例子:

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
            }
        }
    }()
}

更多详情,请参阅文档

答案 1 :(得分:1)

将以下内容视为一个被黑客攻击的例子。

我不确定正确关闭tail.Tail的程序,假设您致电StopStopAtEOF然后Cleanup

还需要改进并发方面。 Goroutines需要优雅地关闭。

进口:

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

检查新文件的功能:

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
}

Tail文件的功能:

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()
}

主要:

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)
    }
}