golang进程启动及监控方式

 更新时间:2026年04月27日 09:09:38   作者:壹零空间  
本文介绍了使用Golang实现进程守护和进程监控的方法,提供了两种具体实现方式:一种是代码集成到业务代码中,通过命令行参数判断是否启动守护进程;另一种是单独编写守护进程程序,不与业务代码耦合,可作为通用的守护进程程序,两种方式各有优缺点,适用于不同的场景

golang进程启动及监控

  • 守护进程(deamon):为任意进程创建守护进程,使进程脱离终端运行
  • 监控进程(forever):创建监控重启进程,使进程被杀死后能够重启

由于近期项目需要,使用go预研开发边缘智能程序,因此就想着通过golang实现进程守护及进程监控的功能,在golang程序中启动子进程,有很好的封装exec.Command,导入包为os/exec,本文主要以此种方式实现,包含以下两种实现方式。

1.1 以集成到业务代码的方式实现

此方式是把相关代码集成到我们需要监控的进程代码中,通过命令行参数来判断是否启用守护进程,其代码如下所示:

test.go

package test

import (
 "flag"
 "fmt"
 "os"
 "os/exec"
 "time"
)
func main() {
 daemon := flag.Bool("deamon", false, "run in daemon and forever")
 flag.Parse()
 //判断是否以守护进程的方式启动
 if *daemon {
  runbydeamon(os.Args) //执行deamon,由其启动主程序
 }
 //业务主程序代码
 fmt.Println("start test Service")
}

//以deamon的方式启动程序,并监控进程
func runbydeamon(args []string) {
 fmt.Printf("PID: %d PPID: %d ARG: %s\n", os.Getpid(), os.Getppid(), os.Args)
 //去掉-deamon运行参数,启动主程序
 for i := 0; i < len(args); {
  if args[i] == "-deamon" && i != len(args)-1 {
   args = append(args[:i], args[i+1:]...)
  } else if args[i] == "-deamon" && i == len(args)-1 {
   args = args[:i]
  } else {
   i++
  }
 }
 //启动子进程,去掉-deamon参数后,执行程序,由于子程序无deamon参数,因此会直接执行业务代码
 for {
  cmd := exec.Command(args[0], args[1:]...)
  cmd.Stdin = os.Stdin
  cmd.Stdout = os.Stdout
  cmd.Stderr = os.Stderr
  err := cmd.Start()//开启子进程
  if err != nil {
   fmt.Fprintf(os.Stderr, "start oasis erir [-] Error: %s\n", err)
   return
  }
  fmt.Println("run oasis bydeamon,pid=", cmd.Process.Pid, ",ppid=", os.Getpid(), "args=", args, "time=", time.Now())
  cmd.Wait() //阻塞等待进程退出
 }
}

通过go buid编写以后,执行"test -deamon"后,由于带有代码会启动两个test进程,第一次启动时由于带有参数"-deamon",因此会调用runbydeamon,此函数会去掉-deamon参数,再次以子进程的方式执行"test",通过cmd.start()启动子进程,子进程由于不带"-deamon",会直接进入业务代码实现,这里会打印:

start test Service,守护进程有一个for循环,一直在等待子进程退出,如果子进程异常退出,守护进程会再次把子进程进程拉起来并等待。

1.2 以单独代码的方式实现

上文实现方式,与业务代码耦合,启动时只需要带有一个参数即可启动守护进程和业务进程,启动比较简单,但是代码与业务耦合在一起,这种写法使得没法复用守护进程,其实守护进程与业务进程没有任何关系,大可提取出来,作为通用的守护进程程序,支持任务进程的后台启动和监控,代码如下:

deamon.go

package deamon

import (
 "flag"
 "fmt"
 "os"
 "os/exec"
 "time"
)
func main() {
 pcmd := flag.String("cmd", "", "run cmd in daemon and forever")
 flag.Parse()
 runbydeamon(*pcmd) //执行deamon,由其启动主程序
}

//以deamon的方式启动程序,并监控进程
func runbydeamon(args string) {
 fmt.Printf("PID: %d PPID: %d ARG: %s\n", os.Getpid(), os.Getppid(), os.Args)
 if cmd==""{
    fmt.Println("cmd is null")
    os.Exit(0)
 }
 //启动子进程,既是去掉-deamon参数后,执行程序,由于子程序无deamon参数,因此会直接执行业务代码
 for {
  cmd := exec.Command(args[1], args[2:]...)
  cmd.Stdin = os.Stdin
  cmd.Stdout = os.Stdout
  cmd.Stderr = os.Stderr
  err := cmd.Start()//开启子进程
  if err != nil {
   fmt.Fprintf(os.Stderr, "start oasis erir [-] Error: %s\n", err)
   return
  }
  fmt.Println("run oasis bydeamon,pid=", cmd.Process.Pid, ",ppid=", os.Getpid(), "args=", args, "time=", time.Now())
  cmd.Wait() //阻塞等待进程退出
 }
}

test.go

package test
import (
 "flag"
 "fmt"
)
func main() {
   fmt.Println("start test Service") 
}

以守护进程的方式启动进程命令:

deamon -cmd “test”

如果执行test要带命令行,可直接作为deamon的命令行传递给test:

deamon -cmd “test” -c “config.yaml”

有关运行参数flag定义,可根据需要自行定义,这里仅是一个例子。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Golang中goto跳转语句的实现

    Golang中goto跳转语句的实现

    本文主要介绍了Golang中goto跳转语句的实现,包括标签的定义、跳转语句的使用、作用域限制、避免滥用的原因以及历史遗留代码中的使用情况,感兴趣的可以了解一下
    2025-03-03
  • Golang Mutex互斥锁源码分析

    Golang Mutex互斥锁源码分析

    本篇文章,我们将一起来探究下Golang Mutex底层是如何实现的,知其然,更要知其所以然。文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-10-10
  • 一文带你玩转Golang Prometheus Eexporter开发

    一文带你玩转Golang Prometheus Eexporter开发

    本文分两大块,一是搞清楚prometheus四种类型的指标Counter,Gauge,Histogram,Summary用golang语言如何构造这4种类型对应的指标,二是搞清楚修改指标值的场景和方式,感兴趣的可以了解一下
    2023-02-02
  • 使用Viper处理Go应用程序的配置方法

    使用Viper处理Go应用程序的配置方法

    Viper是一个应用程序配置解决方案,用于Go应用程序,它支持JSON、TOML、YAML、HCL、envfile和Java properties配置文件格式,这篇文章主要介绍了使用Viper处理Go应用程序的配置,需要的朋友可以参考下
    2023-09-09
  • go doudou应用中使用注解示例详解

    go doudou应用中使用注解示例详解

    这篇文章主要为大家介绍了go doudou应用中使用注解示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • golang的强制类型转换实现

    golang的强制类型转换实现

    这篇文章主要介绍了golang的强制类型转换实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 浅谈Go语言不提供隐式数字转换的原因

    浅谈Go语言不提供隐式数字转换的原因

    本文主要介绍了浅谈Go语言不提供隐式数字转换的原因,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Go单元测试利器testify使用示例详解

    Go单元测试利器testify使用示例详解

    这篇文章主要为大家介绍了Go单元测试利器testify使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 关于Go 是传值还是传引用?

    关于Go 是传值还是传引用?

    这篇文章主要讨论Go语言 是传值还是传引用?文章先从Go 官方的定义展开,随后是传值和传引用得介绍到map 和 slice得区别,需要的小伙伴可以参考一下文章得具体内容
    2021-10-10
  • Go语言变量与基础数据类型详情

    Go语言变量与基础数据类型详情

    Go 是静态(编译型)语言,是区别于解释型语言的弱类型语言(静态:类型固定,强类型:不同类型不允许直接运算),下面文章将对其进行详细介绍,需要的朋友可以参考一下
    2021-09-09

最新评论