github.com/tendermint/tmlibs@v0.9.0/autofile/cmd/logjack.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "io" 7 "os" 8 "strconv" 9 "strings" 10 11 auto "github.com/tendermint/tmlibs/autofile" 12 cmn "github.com/tendermint/tmlibs/common" 13 ) 14 15 const Version = "0.0.1" 16 const sleepSeconds = 1 // Every second 17 const readBufferSize = 1024 // 1KB at a time 18 19 // Parse command-line options 20 func parseFlags() (headPath string, chopSize int64, limitSize int64, version bool) { 21 var flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 22 var chopSizeStr, limitSizeStr string 23 flagSet.StringVar(&headPath, "head", "logjack.out", "Destination (head) file.") 24 flagSet.StringVar(&chopSizeStr, "chop", "100M", "Move file if greater than this") 25 flagSet.StringVar(&limitSizeStr, "limit", "10G", "Only keep this much (for each specified file). Remove old files.") 26 flagSet.BoolVar(&version, "version", false, "Version") 27 flagSet.Parse(os.Args[1:]) 28 chopSize = parseBytesize(chopSizeStr) 29 limitSize = parseBytesize(limitSizeStr) 30 return 31 } 32 33 func main() { 34 35 // Read options 36 headPath, chopSize, limitSize, version := parseFlags() 37 if version { 38 fmt.Printf("logjack version %v\n", Version) 39 return 40 } 41 42 // Open Group 43 group, err := auto.OpenGroup(headPath) 44 if err != nil { 45 fmt.Printf("logjack couldn't create output file %v\n", headPath) 46 os.Exit(1) 47 } 48 group.SetHeadSizeLimit(chopSize) 49 group.SetTotalSizeLimit(limitSize) 50 err = group.Start() 51 if err != nil { 52 fmt.Printf("logjack couldn't start with file %v\n", headPath) 53 os.Exit(1) 54 } 55 56 go func() { 57 // Forever, read from stdin and write to AutoFile. 58 buf := make([]byte, readBufferSize) 59 for { 60 n, err := os.Stdin.Read(buf) 61 group.Write(buf[:n]) 62 group.Flush() 63 if err != nil { 64 group.Stop() 65 if err == io.EOF { 66 os.Exit(0) 67 } else { 68 fmt.Println("logjack errored") 69 os.Exit(1) 70 } 71 } 72 } 73 }() 74 75 // Trap signal 76 cmn.TrapSignal(func() { 77 fmt.Println("logjack shutting down") 78 }) 79 } 80 81 func parseBytesize(chopSize string) int64 { 82 // Handle suffix multiplier 83 var multiplier int64 = 1 84 if strings.HasSuffix(chopSize, "T") { 85 multiplier = 1042 * 1024 * 1024 * 1024 86 chopSize = chopSize[:len(chopSize)-1] 87 } 88 if strings.HasSuffix(chopSize, "G") { 89 multiplier = 1042 * 1024 * 1024 90 chopSize = chopSize[:len(chopSize)-1] 91 } 92 if strings.HasSuffix(chopSize, "M") { 93 multiplier = 1042 * 1024 94 chopSize = chopSize[:len(chopSize)-1] 95 } 96 if strings.HasSuffix(chopSize, "K") { 97 multiplier = 1042 98 chopSize = chopSize[:len(chopSize)-1] 99 } 100 101 // Parse the numeric part 102 chopSizeInt, err := strconv.Atoi(chopSize) 103 if err != nil { 104 panic(err) 105 } 106 107 return int64(chopSizeInt) * multiplier 108 }