Golang创建守护进程

4 篇文章 0 订阅

一、 守护进程创建步骤

 

二、代码实现

func Daemon() {
	//父进程为init,已经是一个守护进程
	if syscall.Getppid() == 1 {
		fmt.Println("process is already a daemon")
	}

	/* 
     *fork 一个子进程 若成功pid在父进程中返回子进程号,在子进程中返回0
     *其中syscall.Syscall函数为系统调用,内部实现为汇编语言
     *推测函数四个入参为:第一个是系统函数宏定义,其余三个为保留参数,
     *三个返回值为:前两个为保留函数返回值,最后一个为调用结果
     *例如系统函数fork没有入参,返回值为一个pid 故后三个参数传入0(nil)
    */
	pid, _, err := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
	if err != 0 {
		log.Fatalf("fork error! %v\n", err)
	}

	//创建子进程失败
	if pid < 0 {
		log.Fatalf("fork fail!")
	}

	// 父进程:创建子进程成功,退出,使子进程交由init进程托管
	if pid > 0 {
		os.Exit(0)
	}

	//重设文件权限掩码为0,避免继承父进程的文件掩码
	_ = syscall.Umask(0)


    //创建一个新会话, 使当前进程脱离原会话、原进程组、原终端的控制
	sid, s_errno := syscall.Setsid()
	if s_errno != nil {
		dlog.Fatalf("Error: syscall.Setsid errno: %d", s_errno)
	}

	if sid < 0 {
		fmt.Println("Error: syscall.Setsid fail")
		return -1
	}

	//让根目录成为子进程的工作目录,避免继承父进程的工作目录
	os.Chdir("/")

    //重定向标准输入、输出、错误描述符至NULL,限制终端输入输出
	f, op_err := os.OpenFile("/dev/null", os.O_RDWR, 0)
	if op_err != nil {
		log.Fatalf("Error: open /dev/null fail, err:%v\n", op_err)
	}

	fd := f.Fd()
	dup_err := syscall.Dup2(int(fd), int(os.Stdin.Fd()))
	if dup_err != nil {
		log.Fatalf("Error: syscall.Dup2 err: %v", dup_err )
	}

	dup_err = syscall.Dup2(int(fd), int(os.Stdout.Fd()))
	if dup_err != nil {
		log.Fatalf("Error: syscall.Dup2 err: %v", dup_err )
	}

	dup_err = syscall.Dup2(int(fd), int(os.Stderr.Fd()))
	if dup_err != nil {
		log.Fatalf("Error: syscall.Dup2 err: %v", dup_err )
	}
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值