Commit 8d83b302 by Bogdan Ungureanu

Adding os/daemon library

parent 2ed57343
......@@ -4,6 +4,7 @@ GO libraries
Libraries
---------
fs/inotify - inotify library for go
fs/inotify - inotify library
net/cluster - simple network cluster
os/daemon - daemonize library
package daemon
import (
"errors"
"flag"
//"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"syscall"
)
type Daemon struct {
ConfigFile string
LogFile string
PidFile string
startServer bool
stopServer bool
restartServer bool
args []string
flagSet *flag.FlagSet
}
func New(AppName string, ConfigFile string, LogFile string, PidFile string) *Daemon {
args := os.Args
daemon := &Daemon{
args: args,
}
flagset := flag.NewFlagSet(AppName, flag.ExitOnError)
flagset.StringVar(&daemon.PidFile,
"pid",
PidFile,
"\tServer PID File",
)
flagset.StringVar(&daemon.ConfigFile,
"config",
ConfigFile,
"\tConfig file",
)
flagset.StringVar(&daemon.LogFile,
"log",
LogFile,
"\tServer log File",
)
flagset.BoolVar(&daemon.startServer,
"start",
false,
"\tStart application and daemonize",
)
flagset.BoolVar(&daemon.stopServer,
"stop",
false,
"\tStop application",
)
flagset.BoolVar(&daemon.restartServer,
"restart",
false,
"\tRestart application",
)
flagset.Usage = func() {
flagset.PrintDefaults()
os.Exit(2)
}
daemon.flagSet = flagset
daemon.flagSet.Parse(args[1:])
return daemon
}
func (d *Daemon) Run() error {
if d.stopServer || d.restartServer {
d.stopProcess()
}
if d.startServer || d.restartServer {
if pid := d.getPid(); pid == 0 {
d.startProcess()
os.Exit(0)
}
return errors.New("Process allready running")
}
if d.stopServer {
os.Exit(0)
}
err := d.setPid()
if err != nil {
return err
}
err = d.setLog()
if err != nil {
return err
}
return nil
}
// Read pid from file , check if process is running
func (d *Daemon) getPid() int {
var pid int
f, err := os.Open(d.PidFile)
if err != nil {
return 0
}
defer f.Close()
buf := make([]byte, 10)
lpid, err := f.Read(buf)
if err == nil {
pid, err = strconv.Atoi(string(buf[:lpid]))
if err != nil {
return 0
}
if err = syscall.Kill(pid, 0); err == nil {
return pid
}
}
return 0
}
// Write pid to file
func (d *Daemon) setPid() error {
pidfile, err := os.OpenFile(
d.PidFile,
os.O_CREATE|os.O_RDWR,
0666,
)
if err != nil {
return err
}
defer pidfile.Close()
pid := os.Getpid()
pidfile.Write([]byte(strconv.Itoa(pid)))
pidfile.Close()
return nil
}
func (d *Daemon) setLog() error {
if os.Getenv("go-daemon-child") == "" {
return nil
}
logfile, err := os.OpenFile(
d.LogFile,
os.O_APPEND|os.O_CREATE|os.O_RDWR,
0666,
)
if err != nil {
return err
}
// Redirect Stdout and Stderr to log
syscall.Dup2(int(logfile.Fd()), 1)
syscall.Dup2(int(logfile.Fd()), 2)
return nil
}
func (d *Daemon) startProcess() error {
procArgs := []string{}
opt := ""
for _, arg := range d.args {
if strings.HasPrefix(arg, "-") {
opt = arg
}
if opt != "-start" && opt != "-stop" && opt != "-restart" {
procArgs = append(procArgs, arg)
}
}
procName := filepath.Base(procArgs[0])
procPath := filepath.Dir(procArgs[0])
procArgs[0] = procName
env := os.Environ()
env = append(env, "go-daemon-child=running")
procAttr := &os.ProcAttr{
Dir: procPath,
Env: env,
Files: []*os.File{nil, nil, nil},
}
_, err := os.StartProcess(procName, procArgs, procAttr)
if err != nil {
return err
}
return nil
}
func (d *Daemon) stopProcess() error {
return nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment