1// Copyright (c) 2015 HPE Software Inc. All rights reserved. 2// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. 3 4package main 5 6import ( 7 "flag" 8 "fmt" 9 "os" 10 11 "github.com/gcla/tail" 12) 13 14func args2config() (tail.Config, int64) { 15 config := tail.Config{Follow: true} 16 n := int64(0) 17 maxlinesize := int(0) 18 flag.Int64Var(&n, "n", 0, "tail from the last Nth location") 19 flag.IntVar(&maxlinesize, "max", 0, "max line size") 20 flag.BoolVar(&config.Follow, "f", false, "wait for additional data to be appended to the file") 21 flag.BoolVar(&config.ReOpen, "F", false, "follow, and track file rename/rotation") 22 flag.BoolVar(&config.Poll, "p", false, "use polling, instead of inotify") 23 flag.Parse() 24 if config.ReOpen { 25 config.Follow = true 26 } 27 return config, n 28} 29 30func main() { 31 config, n := args2config() 32 if flag.NFlag() < 1 { 33 fmt.Println("need one or more files as arguments") 34 os.Exit(1) 35 } 36 37 if n != 0 { 38 config.Location = &tail.SeekInfo{-n, os.SEEK_END} 39 } 40 41 done := make(chan bool) 42 for _, filename := range flag.Args() { 43 go tailFile(filename, config, done) 44 } 45 46 for _, _ = range flag.Args() { 47 <-done 48 } 49} 50 51func tailFile(filename string, config tail.Config, done chan bool) { 52 defer func() { done <- true }() 53 t, err := tail.TailFile(filename, config) 54 if err != nil { 55 fmt.Println(err) 56 return 57 } 58 for line := range t.Bytes { 59 fmt.Println(line.Text) 60 } 61 err = t.Wait() 62 if err != nil { 63 fmt.Println(err) 64 } 65} 66