github.com/Oyster-zx/tendermint@v0.34.24-fork/libs/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/tendermint/libs/autofile" 12 tmos "github.com/tendermint/tendermint/libs/os" 13 ) 14 15 const Version = "0.0.1" 16 const readBufferSize = 1024 // 1KB at a time 17 18 // Parse command-line options 19 func parseFlags() (headPath string, chopSize int64, limitSize int64, version bool) { 20 var flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 21 var chopSizeStr, limitSizeStr string 22 flagSet.StringVar(&headPath, "head", "logjack.out", "Destination (head) file.") 23 flagSet.StringVar(&chopSizeStr, "chop", "100M", "Move file if greater than this") 24 flagSet.StringVar(&limitSizeStr, "limit", "10G", "Only keep this much (for each specified file). Remove old files.") 25 flagSet.BoolVar(&version, "version", false, "Version") 26 if err := flagSet.Parse(os.Args[1:]); err != nil { 27 fmt.Printf("err parsing flag: %v\n", err) 28 os.Exit(1) 29 } 30 chopSize = parseBytesize(chopSizeStr) 31 limitSize = parseBytesize(limitSizeStr) 32 return 33 } 34 35 type fmtLogger struct{} 36 37 func (fmtLogger) Info(msg string, keyvals ...interface{}) { 38 strs := make([]string, len(keyvals)) 39 for i, kv := range keyvals { 40 strs[i] = fmt.Sprintf("%v", kv) 41 } 42 fmt.Printf("%s %s\n", msg, strings.Join(strs, ",")) 43 } 44 45 func main() { 46 // Stop upon receiving SIGTERM or CTRL-C. 47 tmos.TrapSignal(fmtLogger{}, func() { 48 fmt.Println("logjack shutting down") 49 }) 50 51 // Read options 52 headPath, chopSize, limitSize, version := parseFlags() 53 if version { 54 fmt.Printf("logjack version %v\n", Version) 55 return 56 } 57 58 // Open Group 59 group, err := auto.OpenGroup(headPath, auto.GroupHeadSizeLimit(chopSize), auto.GroupTotalSizeLimit(limitSize)) 60 if err != nil { 61 fmt.Printf("logjack couldn't create output file %v\n", headPath) 62 os.Exit(1) 63 } 64 65 if err = group.Start(); err != nil { 66 fmt.Printf("logjack couldn't start with file %v\n", headPath) 67 os.Exit(1) 68 } 69 70 // Forever read from stdin and write to AutoFile. 71 buf := make([]byte, readBufferSize) 72 for { 73 n, err := os.Stdin.Read(buf) 74 if err != nil { 75 if err := group.Stop(); err != nil { 76 fmt.Fprintf(os.Stderr, "logjack stopped with error %v\n", headPath) 77 os.Exit(1) 78 } 79 if err == io.EOF { 80 os.Exit(0) 81 } else { 82 fmt.Println("logjack errored") 83 os.Exit(1) 84 } 85 } 86 _, err = group.Write(buf[:n]) 87 if err != nil { 88 fmt.Fprintf(os.Stderr, "logjack failed write with error %v\n", headPath) 89 os.Exit(1) 90 } 91 if err := group.FlushAndSync(); err != nil { 92 fmt.Fprintf(os.Stderr, "logjack flushsync fail with error %v\n", headPath) 93 os.Exit(1) 94 } 95 } 96 } 97 98 func parseBytesize(chopSize string) int64 { 99 // Handle suffix multiplier 100 var multiplier int64 = 1 101 if strings.HasSuffix(chopSize, "T") { 102 multiplier = 1042 * 1024 * 1024 * 1024 103 chopSize = chopSize[:len(chopSize)-1] 104 } 105 if strings.HasSuffix(chopSize, "G") { 106 multiplier = 1042 * 1024 * 1024 107 chopSize = chopSize[:len(chopSize)-1] 108 } 109 if strings.HasSuffix(chopSize, "M") { 110 multiplier = 1042 * 1024 111 chopSize = chopSize[:len(chopSize)-1] 112 } 113 if strings.HasSuffix(chopSize, "K") { 114 multiplier = 1042 115 chopSize = chopSize[:len(chopSize)-1] 116 } 117 118 // Parse the numeric part 119 chopSizeInt, err := strconv.Atoi(chopSize) 120 if err != nil { 121 panic(err) 122 } 123 124 return int64(chopSizeInt) * multiplier 125 }