9
9
10
10
``` Go
11
11
12
- d := flag.Bool (" d" , false , " Whether or not to launch in the background(like a daemon)" )
13
- if *d {
14
- cmd := exec.Command (os.Args [0 ],
15
- " -close-fds" ,
16
- " -addr" , *addr,
17
- " -call" , *call,
18
- )
19
- serr , err := cmd.StderrPipe ()
20
- if err != nil {
21
- log.Fatalln (err)
22
- }
23
- err = cmd.Start ()
24
- if err != nil {
25
- log.Fatalln (err)
26
- }
27
- s , err := ioutil.ReadAll (serr)
28
- s = bytes.TrimSpace (s)
29
- if bytes.HasPrefix (s, []byte (" addr: " )) {
30
- fmt.Println (string (s))
31
- cmd.Process .Release ()
32
- } else {
33
- log.Printf (" unexpected response from MarGo: `%s ` error: `%v `\n " , s, err)
34
- cmd.Process .Kill ()
35
- }
12
+ d := flag.Bool (" d" , false , " Whether or not to launch in the background(like a daemon)" )
13
+ if *d {
14
+ cmd := exec.Command (os.Args [0 ],
15
+ " -close-fds" ,
16
+ " -addr" , *addr,
17
+ " -call" , *call,
18
+ )
19
+ serr , err := cmd.StderrPipe ()
20
+ if err != nil {
21
+ log.Fatalln (err)
36
22
}
23
+ err = cmd.Start ()
24
+ if err != nil {
25
+ log.Fatalln (err)
26
+ }
27
+ s , err := ioutil.ReadAll (serr)
28
+ s = bytes.TrimSpace (s)
29
+ if bytes.HasPrefix (s, []byte (" addr: " )) {
30
+ fmt.Println (string (s))
31
+ cmd.Process .Release ()
32
+ } else {
33
+ log.Printf (" unexpected response from MarGo: `%s ` error: `%v `\n " , s, err)
34
+ cmd.Process .Kill ()
35
+ }
36
+ }
37
37
```
38
38
39
39
- 另一种是利用syscall的方案,但是这个方案并不完善:
40
40
``` Go
41
41
42
- package main
43
-
44
- import (
45
- " log"
46
- " os"
47
- " syscall"
48
- )
49
-
50
- func daemon (nochdir , noclose int ) int {
51
- var ret , ret2 uintptr
52
- var err uintptr
53
-
54
- darwin := syscall.OS == " darwin"
55
-
56
- // already a daemon
57
- if syscall.Getppid () == 1 {
58
- return 0
59
- }
60
-
61
- // fork off the parent process
62
- ret, ret2, err = syscall.RawSyscall (syscall.SYS_FORK , 0 , 0 , 0 )
63
- if err != 0 {
64
- return -1
65
- }
66
-
67
- // failure
68
- if ret2 < 0 {
69
- os.Exit (-1 )
70
- }
71
-
72
- // handle exception for darwin
73
- if darwin && ret2 == 1 {
74
- ret = 0
75
- }
76
-
77
- // if we got a good PID, then we call exit the parent process.
78
- if ret > 0 {
79
- os.Exit (0 )
80
- }
81
-
82
- /* Change the file mode mask */
83
- _ = syscall.Umask (0 )
84
-
85
- // create a new SID for the child process
86
- s_ret , s_errno := syscall.Setsid ()
87
- if s_errno != 0 {
88
- log.Printf (" Error: syscall.Setsid errno: %d " , s_errno)
89
- }
90
- if s_ret < 0 {
91
- return -1
92
- }
93
-
94
- if nochdir == 0 {
95
- os.Chdir (" /" )
96
- }
97
-
98
- if noclose == 0 {
99
- f , e := os.OpenFile (" /dev/null" , os.O_RDWR , 0 )
100
- if e == nil {
101
- fd := f.Fd ()
102
- syscall.Dup2 (fd, os.Stdin .Fd ())
103
- syscall.Dup2 (fd, os.Stdout .Fd ())
104
- syscall.Dup2 (fd, os.Stderr .Fd ())
105
- }
106
- }
107
-
42
+ package main
43
+
44
+ import (
45
+ " log"
46
+ " os"
47
+ " syscall"
48
+ )
49
+
50
+ func daemon (nochdir , noclose int ) int {
51
+ var ret , ret2 uintptr
52
+ var err uintptr
53
+
54
+ darwin := syscall.OS == " darwin"
55
+
56
+ // already a daemon
57
+ if syscall.Getppid () == 1 {
108
58
return 0
109
- }
59
+ }
60
+
61
+ // fork off the parent process
62
+ ret, ret2, err = syscall.RawSyscall (syscall.SYS_FORK , 0 , 0 , 0 )
63
+ if err != 0 {
64
+ return -1
65
+ }
66
+
67
+ // failure
68
+ if ret2 < 0 {
69
+ os.Exit (-1 )
70
+ }
71
+
72
+ // handle exception for darwin
73
+ if darwin && ret2 == 1 {
74
+ ret = 0
75
+ }
76
+
77
+ // if we got a good PID, then we call exit the parent process.
78
+ if ret > 0 {
79
+ os.Exit (0 )
80
+ }
81
+
82
+ /* Change the file mode mask */
83
+ _ = syscall.Umask (0 )
84
+
85
+ // create a new SID for the child process
86
+ s_ret , s_errno := syscall.Setsid ()
87
+ if s_errno != 0 {
88
+ log.Printf (" Error: syscall.Setsid errno: %d " , s_errno)
89
+ }
90
+ if s_ret < 0 {
91
+ return -1
92
+ }
93
+
94
+ if nochdir == 0 {
95
+ os.Chdir (" /" )
96
+ }
97
+
98
+ if noclose == 0 {
99
+ f , e := os.OpenFile (" /dev/null" , os.O_RDWR , 0 )
100
+ if e == nil {
101
+ fd := f.Fd ()
102
+ syscall.Dup2 (fd, os.Stdin .Fd ())
103
+ syscall.Dup2 (fd, os.Stdout .Fd ())
104
+ syscall.Dup2 (fd, os.Stderr .Fd ())
105
+ }
106
+ }
107
+
108
+ return 0
109
+ }
110
110
```
111
111
112
112
上面提出了两种实现Go的daemon方案,但是我还是不推荐大家这样去实现,因为官方还没有正式的宣布支持daemon,当然第一种方案目前来看是比较可行的,而且目前开源库skynet也在采用这个方案做daemon。
@@ -128,45 +128,45 @@ Supervisord默认的配置文件路径为/etc/supervisord.conf,通过文本编
128
128
129
129
``` conf
130
130
131
- ;/etc/supervisord.conf
132
- [unix_http_server]
133
- file = /var/run/supervisord.sock
134
- chmod = 0777
135
- chown= root:root
136
-
137
- [inet_http_server]
138
- # Web管理界面设定
139
- port=9001
140
- username = admin
141
- password = yourpassword
142
-
143
- [supervisorctl]
144
- ; 必须和'unix_http_server'里面的设定匹配
145
- serverurl = unix:///var/run/supervisord.sock
146
-
147
- [supervisord]
148
- logfile=/var/log/supervisord/supervisord.log ; (main log file;default $CWD/supervisord.log)
149
- logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
150
- logfile_backups=10 ; (num of main logfile rotation backups;default 10)
151
- loglevel=info ; (log level;default info; others: debug,warn,trace)
152
- pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
153
- nodaemon=true ; (start in foreground if true;default false)
154
- minfds=1024 ; (min. avail startup file descriptors;default 1024)
155
- minprocs=200 ; (min. avail process descriptors;default 200)
156
- user=root ; (default is current user, required if root)
157
- childlogdir=/var/log/supervisord/ ; ('AUTO' child log dir, default $TEMP)
158
-
159
- [rpcinterface:supervisor]
160
- supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
161
-
162
- ; 管理的单个进程的配置,可以添加多个program
163
- [program:blogdemon]
164
- command=/data/blog/blogdemon
165
- autostart = true
166
- startsecs = 5
167
- user = root
168
- redirect_stderr = true
169
- stdout_logfile = /var/log/supervisord/blogdemon.log
131
+ ;/etc/supervisord.conf
132
+ [unix_http_server]
133
+ file = /var/run/supervisord.sock
134
+ chmod = 0777
135
+ chown= root:root
136
+
137
+ [inet_http_server]
138
+ # Web管理界面设定
139
+ port=9001
140
+ username = admin
141
+ password = yourpassword
142
+
143
+ [supervisorctl]
144
+ ; 必须和'unix_http_server'里面的设定匹配
145
+ serverurl = unix:///var/run/supervisord.sock
146
+
147
+ [supervisord]
148
+ logfile=/var/log/supervisord/supervisord.log ; (main log file;default $CWD/supervisord.log)
149
+ logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
150
+ logfile_backups=10 ; (num of main logfile rotation backups;default 10)
151
+ loglevel=info ; (log level;default info; others: debug,warn,trace)
152
+ pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
153
+ nodaemon=true ; (start in foreground if true;default false)
154
+ minfds=1024 ; (min. avail startup file descriptors;default 1024)
155
+ minprocs=200 ; (min. avail process descriptors;default 200)
156
+ user=root ; (default is current user, required if root)
157
+ childlogdir=/var/log/supervisord/ ; ('AUTO' child log dir, default $TEMP)
158
+
159
+ [rpcinterface:supervisor]
160
+ supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
161
+
162
+ ; 管理的单个进程的配置,可以添加多个program
163
+ [program:blogdemon]
164
+ command=/data/blog/blogdemon
165
+ autostart = true
166
+ startsecs = 5
167
+ user = root
168
+ redirect_stderr = true
169
+ stdout_logfile = /var/log/supervisord/blogdemon.log
170
170
171
171
```
172
172
### Supervisord管理
0 commit comments