这是StackOverFlow上写的,
http://stackoverflow.com/questions/10027477/golang-fork-process/10070021#10070021
还有官网的
http://code.google.com/p/go/issues/detail?id=227
我自己试图抄了一段代码,可以工作,但问题在于我在子进程里面调用了一下time.Sleep后,子进程就不动了。用strace看到子进程卡在epoll调用上。
请问大家是怎么解决这个问题的?就用很土的nohup ./go-exec &
这种shell来实现吗?
package main
import (
"log"
"os"
"runtime"
"errors"
"syscall"
)
func daemon(chdir bool, closeStd bool) (err error){
var ret, ret2 uintptr
var er syscall.Errno
darwin := runtime.GOOS == "darwin"
// already a daemon
if syscall.Getppid() == 1 {
return
}
// fork off the parent process
ret, ret2, er = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0)
if er != 0 {
err = errors.New("fork fail")
return
}
// failure
if ret2 < 0 {
err = errors.New("fork fail")
os.Exit(-1)
}
// handle exception for darwin
if darwin && ret2 == 1 {
ret = 0
}
// if we got a good PID, then we call exit the parent process.
if ret > 0 {
os.Exit(0)
}
/* Change the file mode mask */
_ = syscall.Umask(0)
// create a new SID for the child process
s_ret, s_errno := syscall.Setsid()
if s_errno != nil {
log.Printf("Error: syscall.Setsid errno: %d", s_errno)
}
if s_ret < 0 {
err = errors.New("setsid fail")
return
}
if chdir {
os.Chdir("/")
}
if closeStd {
f, e := os.OpenFile("/dev/null", os.O_RDWR, 0)
if e == nil {
fd := f.Fd()
syscall.Dup2(int(fd), int(os.Stdin.Fd()))
syscall.Dup2(int(fd), int(os.Stdout.Fd()))
syscall.Dup2(int(fd), int(os.Stderr.Fd()))
}
}
return
}
我是这么解决的,使用了 https://github.com/9466/daemon
Fork 自 https://github.com/VividCortex/godaemon
他使用了三次启动,第三次并不是很必要,我给Fork过来干掉了。