Go语言编程练习#2-守护进程

=Start=

缘由:

之前在第一次学习Go 语言的时候其实整理了一篇文章「Linux下守护进程的Golang语言实现」,但因为后续有其他事情,所以就没有继续下去了。最近刚好在复习Go 语言,所以想着再整理实践一下用Go 语言实现守护进程的功能,就有了这篇文章。

正文:

参考解答:

首先,如果你只是想实现类似于守护进程在后台默默运行的功能的话,可以考虑先用 go build 命令构建出可执行程序,然后(二者选其一即可):

  1. 借助 daemonize 或 upstart 将进程以daemon形式运行;
  2. 使用 nohup 结合 & 的方式,再加上 supervisor 管理。

 

如果你还是希望能用Go 语言实现一个daemon进程,可以参考一下这段代码(在Linux环境下测试验证OK,macOS未通过):

如果你用C或是其它编程语言开发过daemon进程的话你就会发现,实现daemon的主要逻辑步骤在各个语言中都是一样的:

1、创建子进程,父进程退出 fork()
2、子进程创建新会话 setsid()
3、再次创建子进程结束当前进程 fork() #通过使进程不再是会话首进程来禁止进程重新打开控制终端
4、改变当前工作目录 chdir()
5、重设文件权限掩码 umask()
6、关闭无关文件描述符 close()

只不过在Go 语言中,对我来说,现在实现起来最大的问题在于——不论是Syscall.RawSyscall()还是Syscall.Syscall()它们的资料都太少了,参数、返回值的功能和作用都只能靠猜……


一个进程是否是守护进程的验证方法(判断是否符合如下要求):
  • 守护进程不应该有控制终端,所以(TTY = ?)
  • 守护进程的父进程ID为1,即init进程
  • 其中 PID != SID 表明该进程不是会话的leader进程,因为第二个fork()的作用
  • 因为 PID != SID 所以该守护进程无法重新打开/控制一个TTY

 

参考链接:

=END=

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/4157.html

《Go语言编程练习#2-守护进程》上有2条评论

  1. 如何在Go的函数中得到调用者函数名?
    https://colobu.com/2018/11/03/get-function-name-in-go/

    有时候在Go的函数调用的过程中,我们需要知道函数被谁调用,比如打印日志信息等。例如下面的函数,我们希望在日志中打印出调用者的名字。

    func printMyName() string {
    pc, _, _, _ := runtime.Caller(1)
    return runtime.FuncForPC(pc).Name()
    }
    func printCallerName() string {
    pc, _, _, _ := runtime.Caller(2)
    return runtime.FuncForPC(pc).Name()
    }

    // func Caller(skip int) (pc uintptr, file string, line int, ok bool)
    Caller可以返回函数调用栈的某一层的程序计数器、文件信息、行号。
    0 代表当前函数,也是调用runtime.Caller的函数。1 代表上一层调用者,以此类推。

  2. golang 后台服务设计精要
    http://litang.me/post/golang-server-design/

    守护进程
    优雅的结束进程
     响应信号
     等待所有协程退出
    goroutine 生命期管理
    数据库操作与 ORM
     标准库中的数据库操作接口
     ORM
    HTTP 服务
     标准库 net/http 包
     httprouter
     middleware
     gin
    总结
    参考资料

发表评论

电子邮件地址不会被公开。 必填项已用*标注