package main import ( "fmt" "io/ioutil" "os" "os/exec" ) type DaemonExec struct { cmd *exec.Cmd lockFile string running bool } func NewDaemonExec(cmd []string, lockFile string) *DaemonExec { if lockFile == "" { lockFile = ".tmp.daemon.lock" } return &DaemonExec{ cmd: exec.Command(cmd[0], cmd[1:]...), lockFile: lockFile, } } func (d *DaemonExec) Start() error { if d.cmd == nil { return fmt.Errorf("cmd is nil") } d.cmd.Stdout = os.Stdout d.cmd.Stderr = os.Stderr err := d.cmd.Start() if err != nil { return fmt.Errorf("start cmd failed: %v", err) } err = ioutil.WriteFile(d.lockFile, []byte( fmt.Sprintf("%d", d.cmd.Process.Pid)), 0644) if err != nil { return fmt.Errorf("write lock file failed: %v", err) } return nil } func (d *DaemonExec) Kill() error { if d.cmd == nil { return fmt.Errorf("cmd is nil") } err := d.cmd.Process.Kill() if err != nil { return fmt.Errorf("kill cmd failed: %v", err) } err = os.Remove(d.lockFile) if err != nil { return fmt.Errorf("remove lock file failed: %v", err) } return nil } func (d *DaemonExec) RunWithExec(cmd []string) error { if d.running { return fmt.Errorf("daemon is running") } d.cmd = exec.Command(cmd[0], cmd[1:]...) err := d.cmd.Start() if err != nil { return fmt.Errorf("start cmd failed: %v", err) } for { if d.cmd.ProcessState != nil { break } } return nil } func main() { if len(os.Args) < 2 { fmt.Printf("Usage: %s [command]\n", os.Args[0]) os.Exit(1) } d := NewDaemonExec(os.Args[1:], "") err := d.Start() if err != nil { fmt.Printf("start daemon failed: %v\n", err) os.Exit(1) } fmt.Printf("start daemon success\n") fmt.Println("press any key to kill daemon") var s string _, err = fmt.Scanln(&s) if err != nil { fmt.Printf("scan input failed: %v\n", err) } err = d.Kill() if err != nil { fmt.Printf("kill daemon failed: %v\n", err) os.Exit(1) } fmt.Printf("kill daemon success\n") }