douzhi9921
2018-04-20 00:41 阅读 14
已采纳

如何重复关闭并建立执行例程?

every one,I am new to golang.I wanna get the data from log file generated by my application.cuz roll-back mechanism, I met some problem.For instance,my target log file is chats.log,it will be renamed to chats.log.2018xxx and a new chats.log will be created.so my go routine that read log file will fail to work. so I need detect the change and shutdown the previous go routine and then establish the new go routine.

I looked for modules that can help me,and I found

func ExampleNewWatcher(fn string, createnoti chan string, wg sync.WaitGroup) {
    wg.Add(1)
    defer wg.Done()
    watcher, err := fsnotify.NewWatcher()
    if err != nil {
        log.Fatal(err)
    }
    defer watcher.Close()

    done := make(chan bool)
    go func() {
        for {
            select {
            case event := <-watcher.Events:
                if event.Op == fsnotify.Create && event.Name==fn{
                        createnoti <- "has been created"
                }
            case err := <-watcher.Errors:
                log.Println("error:", err)
            }
        }
    }()

    err = watcher.Add("./")
    if err != nil {
        log.Fatal(err)
    }
    <-done
}

I use fsnotify to detech the change,and make sure the event of file is my log file,and then send some message to a channel.

this is my worker go routine:

func tailer(fn string,isfollow bool, outchan chan string, done <-chan interface{},wg sync.WaitGroup) error {
    wg.Add(1)
    defer wg.Done()
    _, err := os.Stat(fn)
    if err != nil{
        panic(err)
    }
    t, err := tail.TailFile(fn, tail.Config{Follow:isfollow})
    if err != nil{
        panic(err)
    }
    defer t.Stop()

    for line := range t.Lines{
        select{
        case outchan <- line.Text:
            case <- done:
                return nil
        }
    }

    return nil
}

I using tail module to read the log file,and I add a done channel to it to shutdown the cycle(I don't know whether I put it in the right way) And I will send every log content to a channel to consuming it. So here is the question:how should I put it together?

ps: Actually,I can use some tool to do this job.like apache-flume,but all of those tools need dependency. Thank you a lot!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    douhui8025 douhui8025 2018-04-20 01:05

    Here is a complete example that reloads and rereads the file as it changes or gets deleted and recreated:

    package main
    
    import (
            "github.com/fsnotify/fsnotify"
            "io/ioutil"
            "log"
    )
    
    const filename = "myfile.txt"
    
    func ReadFile(filename string) string {
            data, err := ioutil.ReadFile(filename)
            if err != nil {
                    log.Println(err)
            }
            return string(data)
    }
    
    func main() {
            watcher, err := fsnotify.NewWatcher()
            if err != nil {
                    log.Fatal(err)
            }
            defer watcher.Close()
            err = watcher.Add("./")
            if err != nil {
                    log.Fatal(err)
            }
            for {
                    select {
                    case event := <-watcher.Events:
                            if event.Op == fsnotify.Create && event.Name == filename {
                                    log.Println(ReadFile(filename))
                            }
                    case err := <-watcher.Errors:
                            log.Println("error:", err)
                    }
            }
    }
    

    Note this doesn't require goroutines, channels or a WaitGroup. Better to keep things simple and reserve those for when they're actually needed.

    点赞 评论 复制链接分享

相关推荐