背景
之前一篇文章中介绍了使用tail追踪显示日志文件内容。
【注】tail包使用方法可以参考上一篇文章
之后,遇到了一种特殊情况:
被监视的文件会被定期删除(日志过大被删等原因),立即重新创建并写入内容(日志)
在代码中重新监视该文件 显示监视了文件(相同文件) 但是并没有获取到写入的新内容
方法
后来查看了tail包内的内容终于找到
需要将之前监视开启的tail kill之后才行
以下是模拟代码
关键:tt.Kill(nil)
var retail = make(chan int, 1)
var killchan = make(chan int, 1)
func Test_tailfile(t *testing.T) {
var file = "test.log"
//模拟日志定期写入 定期删除
go write(file)
//监听日志文件 定期汇总
go tailfile(file)
//测试30s 设置重新监听
ticker := time.NewTicker(30 * time.Second)
for {
select {
case <-ticker.C:
return
case <-retail:
go tailfile(file)
}
}
}
//监听日志文件
func tailfile(file string) {
config := tail.Config{}
config.Follow = true
seek := &tail.SeekInfo{}
seek.Offset = 0
seek.Whence = os.SEEK_END
config.Location = seek
var stopchan = make(chan int, 1)
Debug("tail", file)
tt, err := tail.TailFile(file, config)
if err != nil {
Error(err)
return
}
//每经过2s汇总一次日志信息(number)
go func() {
ticker := time.NewTicker(2 * time.Second)
for {
select {
case <-ticker.C:
l := &tail.Line{}
l.Text = "sum"
tt.Lines <- l
case <-stopchan:
Debug("stop sum")
killchan <- 1 //防止定时写入已关闭的tail
return
}
}
}()
var num int
for line := range tt.Lines {
linestr := line.Text
//提取有用日志信息
if strings.Contains(linestr, "continue") {
num += 1
}
//接收到汇总信号
if linestr == "sum" {
Debug("sum log", num)
//没有数据 重新获取
if num == 0 {
Error("not get loginfo restart")
stopchan <- 1
<-killchan
tt.Kill(nil)
retail <- 1
return
}
//数据清空
num = 0
}
}
}
//模拟日志输入
func write(file string) {
var i int
for {
time.Sleep(time.Second)
f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
Error(err.Error())
}
_, err = f.Write([]byte("continue \n"))
if err != nil {
Error(err.Error())
}
f.Close()
i += 1
Debug("add log", i)
if i > 10 {
//十条日志后 删除日志文件重新建立
Debug("remove file")
os.Remove(file)
i = 0
}
}
}
如果没有Kill直接tail.TailFile() 可以看到下图的结果
虽然显示监听了但并没有监听到新建立文件内的内容
kill之后重新监听则可以正常获取到新文件内的内容