1、使用nohup ./commond & 这种方法最简单.
nohup这个命令可以把程序放后台运行,顺便通过1>和2>把标准输出和标准错误重定向到文件,这样程序崩溃时才会有记录可查,这两者和程序的日志最好是分开,混在一起没办法判断轻重缓急:
nohup ./server 1> server.out 2> server.err
进程启动时候记录下自己的pid:
if pid := syscall.Getpid(); pid != 1 {
ioutil.WriteFile("server.pid", []byte(strconv.Itoa(pid)), 0777)
defer os.Remove("server.pid")
}
同时监听系统发来的kill信号,在收到kill信号时做些收尾工作:
signal.Notify(sigTERM, syscall.SIGTERM)
这样就可以用kill命令关闭服务进程了:
kill `cat game_server.pid`
2、这种方法可以使用信号.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
if os.Getppid() != 1 {
args := append([]string{os.Args[0]}, os.Args[1:]...)
os.StartProcess(os.Args[0], args, &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}})
return
}
go func() {
var c chan os.Signal = make(chan os.Signal, 1)
go signal.Notify(c, os.Kill, os.Interrupt, syscall.SIGHUP, syscall.SIGUSR2)
File, err := os.Create("/tmp/收到的信号.")
defer File.Close()
for {
s := <-c
File.WriteString(s.String())
}
}()
F, err := os.Create("/tmp/log")
if err != nil {
fmt.Println(err)
return
}
defer F.Close()
for {
fmt.Fprintln(F, "Hello World")
time.Sleep(3e9)
}
}
3、这种方法比较底层,但是不能使用信号
package main
import (
"fmt"
"log"
"os"
"os/signal"
"runtime"
"syscall"
"time"
)
func daemon(nochdir, noclose int) int {
var ret, ret2 uintptr
var err syscall.Errno
darwin := runtime.GOOS == "darwin"
// already a daemon
if syscall.Getppid() == 1 {
return 0
}
// fork off the parent process
ret, ret2, err = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0)
if err != 0 {
return -1
}
// failure
if ret2 < 0 {
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 {
return -1
}
if nochdir == 0 {
os.Chdir("/")
}
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()))
}
}
return 0
}
func main() {
daemon(0, 1)
for {
fmt.Println("hello")
time.Sleep(1 * time.Second)
}
}