golang的守护进程化代码,参考了网上的代码,结合自己的项目,去掉了一些没用的代码,增加了fork时候的判断处理,我的机器是freebsd,fork会报errno:0,忽略,原因见代码注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
func Daemonize(nochdir, noclose int) error {
   var hLog *log.Logger
   hLog=LogInit();
   var ret, ret2 uintptr
   var err error
   Log( hLog, fmt.Sprintf("common.Daemonize][current ppid:%d", syscall.Getppid()) )

   //already a daemon
   if syscall.Getppid() == 1 {
       return nil
   }
   Log(hLog,"common.Daemonize][will daemonize")

   //fork off the parent process
   ret, ret2, err = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0)
   if err != nil {
       var s string
       s=fmt.Sprintf("%T",err)
       if s != "syscall.Errno" {
           Log(hLog,"common.Daemonize][fork err:"+s)
               return err
       } else {
           Log(hLog,"common.Daemonize][fork no err:"+err.Error())
           //no problem see http://www.ibm.com/developerworks/aix/library/au-errnovariable/
       }
   }

   //failure
   if ret2 < 0 {
       os.Exit(-1)
   }

   //if we got a good PID, then we call exit the parent process.
   if ret > 0 {
       os.Exit(0)
   }
   Log(hLog,"common.Daemonize][forked,we in forked process")

   /* Change the file mode mask */
   _ = syscall.Umask(0)
   Log(hLog,"common.Daemonize][umask zero")

   //create a new SID for the child process
   s_ret, s_errno := syscall.Setsid()
   if s_ret < 0 || s_errno != nil {
       log.Printf("common.Daemonize][Error: syscall.Setsid errno: %d", s_errno)
   }
   Log(hLog,"common.Daemonize][sid seted")

   if nochdir == 0 {
       os.Chdir("/")
       Log(hLog,"common.Daemonize][chdir to root")
   }

   if noclose == 0 {
       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()))
           Log(hLog,"common.Daemonize][fs closed")
       }
   }

   Log(hLog,"common.Daemonize][daemonize done")
   return nil
}

发表评论