zoukankan      html  css  js  c++  java
  • Go语言daemon启动的解决方法.linux平台

    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)
    	}
    }
    
  • 相关阅读:
    并发与多线程
    java多线程--死锁
    java变量
    StringStringBufferStringBuilder区别
    java8新特性
    spring自动装配和通过java实现装配
    CSP -- 运营商内容劫持(广告)的终结者
    【Composer】实战操作二:自己创建composer包并提交
    【个人重点】开发中应该重视的几点
    【Composer】实战操作一:使用库
  • 原文地址:https://www.cnblogs.com/enumx/p/12316240.html
Copyright © 2011-2022 走看看