From 411dd7dff5308d4f1a1ee2c6358b0b050c82c850 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 5 Nov 2015 14:07:34 -0700 Subject: [PATCH] New -log flag to direct log output to desired place Log file can also be stdout or stderr. Log output is disabled by default now, which makes it more feasible to add more log statements to trace program flow in debugging situations. --- caddy/caddy.go | 9 ++++----- main.go | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/caddy/caddy.go b/caddy/caddy.go index 952480769..ae01593ec 100644 --- a/caddy/caddy.go +++ b/caddy/caddy.go @@ -23,7 +23,6 @@ import ( "errors" "fmt" "io/ioutil" - "log" "net" "os" "path" @@ -183,25 +182,25 @@ func startServers(groupings Group) error { for _, group := range groupings { s, err := server.New(group.BindAddr.String(), group.Configs) if err != nil { - log.Fatal(err) + return err } s.HTTP2 = HTTP2 // TODO: This setting is temporary var ln server.ListenerFile if IsRestart() { // Look up this server's listener in the map of inherited file descriptors; - // if we don't have one, we must make a new one. + // if we don't have one, we must make a new one (later). if fdIndex, ok := loadedGob.ListenerFds[s.Addr]; ok { file := os.NewFile(fdIndex, "") fln, err := net.FileListener(file) if err != nil { - log.Fatal(err) + return err } ln, ok = fln.(server.ListenerFile) if !ok { - log.Fatal("listener was not a ListenerFile") + return errors.New("listener for " + s.Addr + " was not a ListenerFile") } delete(loadedGob.ListenerFds, s.Addr) // mark it as used diff --git a/main.go b/main.go index 3aa99a4dd..e2e6b552d 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ var ( cpu string version bool revoke string + logfile string ) const ( @@ -43,14 +44,31 @@ func init() { flag.BoolVar(&letsencrypt.Agreed, "agree", false, "Agree to Let's Encrypt Subscriber Agreement") flag.StringVar(&letsencrypt.DefaultEmail, "email", "", "Default Let's Encrypt account email address") flag.StringVar(&revoke, "revoke", "", "Hostname for which to revoke the certificate") + flag.StringVar(&logfile, "log", "", "Process log file") } func main() { - flag.Parse() + flag.Parse() // called here in main() to allow other packages to set flags in their inits caddy.AppName = appName caddy.AppVersion = appVersion + // set up process log before anything bad happens + switch logfile { + case "stdout": + log.SetOutput(os.Stdout) + case "stderr": + log.SetOutput(os.Stderr) + case "": + log.SetOutput(ioutil.Discard) + default: + file, err := os.Create(logfile) + if err != nil { + log.Fatalf("Error opening log file: %v", err) + } + log.SetOutput(file) + } + if version { fmt.Printf("%s %s\n", caddy.AppName, caddy.AppVersion) os.Exit(0) @@ -67,13 +85,13 @@ func main() { // Set CPU cap err := setCPU(cpu) if err != nil { - log.Fatal(err) + mustLogFatal(err) } // Get Caddyfile input caddyfile, err := caddy.LoadCaddyfile(loadCaddyfile) if err != nil { - log.Fatal(err) + mustLogFatal(err) } // Start your engines @@ -82,7 +100,7 @@ func main() { if caddy.IsRestart() { log.Println("error starting servers:", err) } else { - log.Fatal(err) + mustLogFatal(err) } } @@ -90,6 +108,14 @@ func main() { caddy.Wait() } +// mustLogFatal just wraps log.Fatal() in a way that ensures the +// output is always printed to stderr so the user can see it, +// even if the process log was not enabled. +func mustLogFatal(args ...interface{}) { + log.SetOutput(os.Stderr) + log.Fatal(args...) +} + func loadCaddyfile() (caddy.Input, error) { // -conf flag if conf != "" {