1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 18:17:03 +00:00

Cycle logfiles on SIGHUP for logrotated

This commit is contained in:
James Hillyerd
2012-11-05 12:50:16 -08:00
parent 8361fa6b6e
commit ac807ed0b0

View File

@@ -13,15 +13,22 @@ import (
"github.com/jhillyerd/inbucket/web" "github.com/jhillyerd/inbucket/web"
golog "log" golog "log"
"os" "os"
"os/signal"
"syscall"
"time" "time"
) )
// Command line flags
var help = flag.Bool("help", false, "Displays this help") var help = flag.Bool("help", false, "Displays this help")
var pidfile = flag.String("pidfile", "none", "Write our PID into the specified file") var pidfile = flag.String("pidfile", "none", "Write our PID into the specified file")
var logfile = flag.String("logfile", "stderr", "Write out log into the specified file") var logfile = flag.String("logfile", "stderr", "Write out log into the specified file")
// startTime is used to calculate uptime of Inbucket
var startTime = time.Now() var startTime = time.Now()
// The file we send log output to, will be nil for stderr or stdout
var logf *os.File
func main() { func main() {
flag.Parse() flag.Parse()
if *help { if *help {
@@ -40,34 +47,37 @@ func main() {
os.Exit(1) os.Exit(1)
} }
// Setup signal handler
sigChan := make(chan os.Signal)
signal.Notify(sigChan, syscall.SIGHUP)
go signalProcessor(sigChan)
// Configure logging, close std* fds // Configure logging, close std* fds
level, _ := config.Config.String("logging", "level")
log.SetLogLevel(level)
if *logfile != "stderr" { if *logfile != "stderr" {
// stderr is the go logging default // stderr is the go logging default
if *logfile == "stdout" { if *logfile == "stdout" {
// set to stdout // set to stdout
golog.SetOutput(os.Stdout) golog.SetOutput(os.Stdout)
} else { } else {
// use specificed log file err = openLogFile()
logf, err := os.OpenFile(*logfile, os.O_WRONLY | os.O_APPEND | os.O_CREATE, 0666)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create %v: %v\n", *logfile, err) fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1) os.Exit(1)
} }
defer logf.Close() defer closeLogFile()
golog.SetOutput(logf)
// close std* streams // close std* streams
os.Stdout.Close() os.Stdout.Close()
os.Stderr.Close() os.Stderr.Close() // Warning: this will hide panic() output
os.Stdin.Close() os.Stdin.Close()
os.Stdout = logf os.Stdout = logf
os.Stderr = logf os.Stderr = logf
} }
} }
level, _ := config.Config.String("logging", "level")
log.SetLogLevel(level)
// Write pidfile if requested // Write pidfile if requested
// TODO: Probably supposed to remove pidfile during shutdown // TODO: Probably supposed to remove pidfile during shutdown
if *pidfile != "none" { if *pidfile != "none" {
@@ -87,6 +97,43 @@ func main() {
web.Start() web.Start()
} }
// openLogFile creates or appends to the logfile passed on commandline
func openLogFile() error {
// use specified log file
var err error
logf, err = os.OpenFile(*logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
return fmt.Errorf("Failed to create %v: %v\n", *logfile, err)
}
golog.SetOutput(logf)
log.Trace("Opened new logfile")
return nil
}
// closeLogFile closes the current logfile
func closeLogFile() error {
log.Trace("Closing logfile")
return logf.Close()
}
// signalProcessor is a goroutine that handles OS signals
func signalProcessor(c <-chan os.Signal) {
for {
sig := <-c
switch sig {
case syscall.SIGHUP:
// Rotate logs if configured
if logf != nil {
log.Info("Recieved SIGHUP, cycling logfile")
closeLogFile()
openLogFile()
} else {
log.Info("Ignoring SIGHUP, logfile not configured")
}
}
}
}
func init() { func init() {
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintln(os.Stderr, "Usage of inbucket [options] <conf file>:") fmt.Fprintln(os.Stderr, "Usage of inbucket [options] <conf file>:")
@@ -96,6 +143,7 @@ func init() {
expvar.Publish("uptime", expvar.Func(uptime)) expvar.Publish("uptime", expvar.Func(uptime))
} }
// uptime() is published as an expvar
func uptime() interface{} { func uptime() interface{} {
return time.Since(startTime) / time.Second return time.Since(startTime) / time.Second
} }