From: Urban Wallasch Date: Wed, 10 Apr 2019 11:15:50 +0000 (+0200) Subject: * Added option to send logging output to file. X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=1aafc37a44c6caea74cf03fe826219f740defb60;p=gogopherd.git * Added option to send logging output to file. * Moved logger to separate source file. --- diff --git a/README.md b/README.md index 7abc929..bef1629 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ options: directory index page (default "index.goph") -c string - configuration file (default "gogopherd.cfg") + configuration file -d allow access to dotfiles @@ -74,6 +74,9 @@ options: -t int connection read/write timeout in seconds (default 60) + -L string + write log to file; empty for stderr + -v produce verbose output ``` diff --git a/config.go b/config.go index 969dfaf..b0ee4bc 100644 --- a/config.go +++ b/config.go @@ -12,6 +12,7 @@ import ( "flag" "fmt" "io/ioutil" + "log" "os" "path" "path/filepath" @@ -31,6 +32,7 @@ var cfg = struct { showdot bool indexes bool timeout int + logfile string verbose bool }{ iface: "localhost", @@ -44,16 +46,16 @@ var cfg = struct { showdot: false, indexes: false, timeout: 60, + logfile: "", verbose: false, } func parseConfigFile(filename string) error { - tracer.Print("reading config from ", filename) file, err := ioutil.ReadFile(filename) if err != nil { - logger.Print("ReadFile: ", err.Error()) return err } + tracer.Print("reading config from ", filename) lines := strings.Split(string(file), "\n") for _, line := range lines { line = strings.TrimSpace(string(line)) @@ -87,20 +89,23 @@ func parseConfigFile(filename string) error { cfg.indexes = strToBool(val) case "timeout": cfg.timeout, _ = strconv.Atoi(val) + case "logfile": + cfg.logfile = val case "verbose": cfg.verbose = strToBool(val) default: - logger.Print("ignoring unknown config item: ", name) + logger.Print("ignoring unknown config file option: ", name) } } return nil } func initialize() { + var err error help := false - cfgfile := "gogopherd.cfg" + cfgfile := "" flag.StringVar(&cfgfile, "c", cfgfile, "configuration file") - flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to") + flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to; empty for any") flag.StringVar(&cfg.port, "p", cfg.port, "TCP port to listen on") flag.StringVar(&cfg.fqdn, "f", cfg.fqdn, "fully qualified domain name") flag.StringVar(&cfg.docroot, "r", cfg.docroot, "document root directory") @@ -112,26 +117,27 @@ func initialize() { flag.BoolVar(&cfg.showdot, "d", cfg.showdot, "allow access to dotfiles") flag.BoolVar(&cfg.indexes, "l", cfg.indexes, "allow generated directory indexes") flag.IntVar(&cfg.timeout, "t", cfg.timeout, "connection read/write timeout in seconds") + flag.StringVar(&cfg.logfile, "L", cfg.logfile, "write log to file; empty for stderr") flag.BoolVar(&cfg.verbose, "v", cfg.verbose, "produce verbose output") flag.Parse() if help { - fmt.Println("Version ", version) + fmt.Println("gogopherd version ", version) flag.Usage() os.Exit(1) } if 0 != len(flag.Args()) { - fmt.Println("Version ", version) - fmt.Println("unrecognized options: ", flag.Args()) + log.Println("unrecognized arguments: ", flag.Args()) flag.Usage() os.Exit(1) } - initUtil(cfg.verbose) + initLogger(cfg.verbose, cfg.logfile) if len(cfgfile) > 0 { - parseConfigFile(cfgfile) + err = parseConfigFile(cfgfile) + checkFatal(err, "parseConfigFile") flag.Parse() + initLogger(cfg.verbose, cfg.logfile) } - var err error cfg.docroot, err = canonicalizePath(cfg.docroot) checkFatal(err, "canonicalizePath "+cfg.docroot) if filepath.IsAbs(cfg.header) { @@ -145,7 +151,7 @@ func initialize() { cfg.idxpage = "" } - tracer.Print("final config after evaluating command line:") + tracer.Print("final config:") tracer.Print("fqdn: ", cfg.fqdn) tracer.Print("iface: ", cfg.iface) tracer.Print("port: ", cfg.port) diff --git a/gogopherd.cfg.example b/gogopherd.cfg.example index c3d00a4..64710ac 100644 --- a/gogopherd.cfg.example +++ b/gogopherd.cfg.example @@ -27,6 +27,9 @@ indexes = true # Connection read and write timeout in seconds timeout = 60 +# Log to file; leave empty for stderr +logfile = "" + # Produce verbose output verbose = false diff --git a/logger.go b/logger.go new file mode 100644 index 0000000..9b6dbca --- /dev/null +++ b/logger.go @@ -0,0 +1,61 @@ +/* + * This file is part of the gogopherd project. + * + * Copyright 2019 Urban Wallasch + * See LICENSE file for more details. + * + */ + +package main + +import ( + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime" +) + +var ( + logger *log.Logger + loggex *log.Logger + tracer *log.Logger + tracex *log.Logger +) + +func initLogger(verbose bool, logfilename string) { + if len(logfilename) > 0 { + logfile, err := os.OpenFile(logfilename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + log.Fatalln("Failed to open log file", logfilename, ":", err) + } + os.Stderr.Close() + os.Stderr = logfile + } + logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) + loggex = log.New(os.Stderr, "", log.Ldate|log.Ltime) + if verbose { + tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) + tracex = log.New(os.Stderr, "", log.Ldate|log.Ltime) + } else { + tracer = log.New(ioutil.Discard, "", 0) + tracex = log.New(ioutil.Discard, "", 0) + } +} + +func checkFatal(err error, msg string) { + if err != nil { + _, file, line, _ := runtime.Caller(1) + loggex.Fatalf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err) + } +} + +func check(err error, msg string) error { + if err != nil && cfg.verbose { + _, file, line, _ := runtime.Caller(1) + tracex.Printf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err) + } + return err +} + +/* EOF */ diff --git a/util.go b/util.go index b31686f..056e112 100644 --- a/util.go +++ b/util.go @@ -12,51 +12,13 @@ import ( "errors" "fmt" "io" - "io/ioutil" - "log" "net/http" "os" "path/filepath" - "runtime" "strings" "time" ) -var ( - logger *log.Logger - loggex *log.Logger - tracer *log.Logger - tracex *log.Logger -) - -func initUtil(verbose bool) { - logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) - loggex = log.New(os.Stderr, "", log.Ldate|log.Ltime) - if verbose { - tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) - tracex = log.New(os.Stderr, "", log.Ldate|log.Ltime) - } else { - tracer = log.New(ioutil.Discard, "", 0) - tracex = log.New(ioutil.Discard, "", 0) - } -} - -func checkFatal(err error, msg string) { - if err != nil { - _, file, line, _ := runtime.Caller(1) - loggex.Printf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err) - os.Exit(1) - } -} - -func check(err error, msg string) error { - if err != nil && cfg.verbose { - _, file, line, _ := runtime.Caller(1) - tracex.Printf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err) - } - return err -} - func canonicalizePath(path string) (string, error) { abs, err := filepath.Abs(path) if check(err, "Abs "+path) != nil {