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

本文最后更新于2018年11月5日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

=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-守护进程》上有5条评论

  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
    总结
    参考资料

  3. Go配置文件热加载 – 发送系统信号
    https://mp.weixin.qq.com/s/fJy5iQqPJvyt2PSsdjYr0w
    https://github.com/apptut/go-labs/blob/master/hotload/signal/main/signal.go

    在日常项目的开发中,我们经常会使用配置文件来保存项目的基本元数据,配置文件的类型有很多,如:JSON、xml、yaml、甚至可能是个纯文本格式的文件。不管是什么类型的配置数据,在某些场景下,我们可会有热更新当前配置文件内容的需求,比如:使用Go运行的一个常驻进程,运行了一个 Web Server 服务进程。

    此时,如果配置文件发生变化,我们如何让当前程序重新读取新的配置文件内容呢?接下来,我们将使用如下两种方式实现配置文件的更新:
    1、使用系统信号(手动式)。
    2、使用inotify, 监听文件修改事件。

    不管是哪一种方式,都会用到Go语言中 goroutine 的概念,我打算使用 goroutine 新起一个协程,新协程目的是用来接收系统信号(signal)或者监听文件被修改的事件,如果你对 goroutine 的概念不是很了解,那么建议你先查阅相关资料。

    鉴于文章篇幅考虑,本文中我们只实现了第一种文件更新方式。下一篇文章中,我们将使用第二种方式:使用inotify监听配置文件的变化,以实现配置文件的自动更新,期待你的关注~

发表评论

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