/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ package main import ( "bytes" "context" "errors" "flag" "fmt" "io" "os" "os/signal" "regexp" "time" "golang.org/x/term" logger "idio.link/go/logger/v3" ) var ( Version, Build string ) var Options = struct { patternRE *regexp.Regexp pattern []byte command string regex, jumpToEnd, matchOnce, printNonmatching, verbose, debug, quiet bool }{} func main() { ctx, cancel := context.WithCancel(context.Background()) ctx = context.WithValue(ctx, "log", logger.NewLogger()) log := ctx.Value("log").(*logger.Logger) done := make(chan struct{}) go func() { sig := make(chan os.Signal, 1) // catch signals signal.Notify(sig, os.Interrupt, os.Kill) for { select { case <-sig: fmt.Println() log.Info("Caught SIGINT/SIGTERM.") cancel() return case <-done: fmt.Println() log.Info("Caught SIGINT/SIGTERM.") return case <-time.After(100 * time.Millisecond): // do nothing; just throttle the cpu } } }() handlePatternFlag := func(p string) (err error) { Options.pattern = []byte(p) Options.patternRE, err = regexp.Compile(p) return err } flags := flag.NewFlagSet("watchlogs", flag.ExitOnError) flags.SetOutput(os.Stderr) flags.BoolVar(&Options.regex, "regex", false, "interpret pattern as a regular expression") flags.BoolVar(&Options.regex, "e", false, "interpret pattern as a regular expression") flags.Func("pattern", "process lines matching pattern", handlePatternFlag) flags.Func("p", "process lines matching pattern", handlePatternFlag) flags.BoolVar(&Options.jumpToEnd, "jump", false, "jump to end of file before processing") flags.BoolVar(&Options.jumpToEnd, "j", false, "jump to end of file before processing") flags.BoolVar(&Options.matchOnce, "once", false, "stop after first matching line is processed") flags.BoolVar(&Options.matchOnce, "1", false, "stop after first matching line is processed") flags.BoolVar(&Options.printNonmatching, "n", false, "print all lines, not just matching ones") flags.BoolVar(&Options.verbose, "v", false, "increase verbosity") flags.BoolVar(&Options.debug, "debug", false, "print debugging information") flags.BoolVar(&Options.debug, "d", false, "print debugging information") flags.BoolVar(&Options.quiet, "quiet", false, "do not print lines") flags.BoolVar(&Options.quiet, "q", false, "do not print lines") flags.StringVar(&Options.command, "command", "", "execute command on match, passing the matched line as input") flags.Parse(os.Args[1:]) logPath := flags.Arg(0) if len(flags.Args()) == 0 { fmt.Fprintf(os.Stderr, "%s %s\n", Version, Build) fmt.Fprintf(os.Stderr, "usage: %s [