Go(第三方庫):03---模擬tail命令(hpcloud/tail包)
阿新 • • 發佈:2020-12-16
技術標籤:Go(第三方庫)模擬tail命令hpcloud/tail包
一、包概述
tail命令
- tail命令語法:https://dongshao.blog.csdn.net/article/details/86589906
- Linux中的tail命令可以使用-n選項來將檔案的尾部指定行數打印出來;並且還提供了-f選項來持續不斷的檢視檔案內容,當檔案有更新時會自動列印
- 這個包就是實現了tail命令中-f的功能,你可以用程式列印一個檔案,當檔案中有資料更新時,程式會自動列印,類似於一個持續檢視檔案內容的功能
- 這個包在日誌收集中可以實時的監測日誌的變化
二、包的下載
- 執行下面的命令下載:
go get github.com/hpcloud/tail/
- 如果是Go Module專案,輸入包名,執行"go mod tidy"也可以
三、演示案例
- 下面先給出一個演示案例,然後再慢慢講解各種資料結構
- 程式碼如下:
package main import ( "fmt" "github.com/hpcloud/tail" "time" ) func main() { // 設定相關選項 config := tail.Config{ ReOpen: true, Follow: true, Location: &tail.SeekInfo{Offset: 0, Whence:2}, MustExist: false, Poll: true, } // 根據上面的選項, 跟蹤當前路徑下的my.log檔案 tails, err := tail.TailFile("./my.log", config) if err != nil { fmt.Println("tail file failed, err: ", err) return } var ( line *tail.Line ok bool ) // 迴圈監聽 for { // 如果檔案中有新的一行資料加入, 那麼這個管道中會有資料 line, ok = <- tails.Lines if !ok { fmt.Printf("tail file close reopen, filename: %s\n", tails.Filename) time.Sleep(time.Second) continue } // 列印新的內容 fmt.Println("line: ", line.Text) } }
- 啟動程式:
- 上面的程式中監聽的是當前路徑下的my.log檔案,我們來到專案當前路徑下,向my.log檔案中加入一行資料(必須要換行,不是一行程式不會監聽到)
- 再次來到程式,可以看到程式列印了相關內容
四、type Config
- Config用來定義檔案被讀取和跟蹤的方式
// 配置用於指定檔案如何被跟蹤 type Config struct { Location *SeekInfo // Seek to this location before tailing ReOpen bool // Reopen recreated files (tail -F) MustExist bool // Fail early if the file does not exist Poll bool // Poll for file changes instead of using inotify Pipe bool // Is a named pipe (mkfifo) RateLimiter *ratelimiter.LeakyBucket // Generic IO Follow bool // Continue looking for new lines (tail -f) MaxLineSize int // If non-zero, split longer lines into multiple lines // Logger, when nil, is set to tail.DefaultLogger // To disable logging: set field to tail.DiscardingLogger Logger logger } // SeekInfo represents arguments to `os.Seek` type SeekInfo struct { Offset int64 Whence int // os.SEEK_* }
- 相關成員:
- Location:指定開始讀取的位置
- ReOpen:true則檔案被刪掉阻塞等待新建該檔案,false則檔案被刪掉時程式結束
- MustExist:true則沒有找到檔案就報錯並結束,false則沒有找到檔案就阻塞保持住
- Poll:使用Linux的Poll函式,poll的作用是把當前的檔案指標掛到等待佇列
- Follow:true則一直阻塞並監聽指定檔案,false則一次讀完就結束程式
五、type Tail
- TailFile可以用來跟蹤檔案
- Lines通道:檔案的輸出流是Lines成員(可以從這個通道中讀取檔案的更新資料),再從Lines通道中讀取完資料之後可以呼叫' Wait '或' Err '方法
type Tail struct {
Filename string
Lines chan *Line
Config
file *os.File
reader *bufio.Reader
watcher watch.FileWatcher
changes *watch.FileChanges
tomb.Tomb // provides: Done, Kill, Dying
lk sync.Mutex
}
func TailFile()
- 該函式在指定的filename檔案和指定的config配合下返回一個Tail物件
func TailFile(filename string, config Config) (*Tail, error)
func (tail *Tail) waitForChanges()
- 等待更改直到檔案被新增、刪除、移動或截斷。當移動或刪除時,如果“重新開啟”為true,檔案將被重新開啟。截短的檔案總是被重新開啟
// waitForChanges waits until the file has been appended, deleted, // moved or truncated. When moved or deleted - the file will be // reopened if ReOpen is true. Truncated files are always reopened. func (tail *Tail) waitForChanges() error
六、type Line
- 這個結構體是用來儲存從Tail中讀取的資訊
type Line struct {
Text string
Time time.Time
Err error // Error from tail
}
func NewLine()
- NewLine返回當前時間的一行
// NewLine returns a Line with present time. func NewLine(text string) *Line { return &Line{text, time.Now(), nil} }
七、總結使用流程
- 首先初始化配置結構體Config
- 呼叫TailFile函式,並傳入檔案路徑和config,返回有個tail的結構體,tail結構體的Lines欄位封裝了拿到的資訊
- 遍歷tail.Lnes欄位,取出資訊(注意這裡要迴圈的取,因為tail可以實現實時監控)