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:
66
inbucket.go
66
inbucket.go
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user