【问题标题】:Golang catch signalsGolang 捕捉信号
【发布时间】:2013-08-09 00:40:28
【问题描述】:

我想在 Go 中实现一个“流程包装器”。基本上它会做的是启动一个进程(比如说一个节点服务器)并监视它(捕获信号,如 SIGKILL、SIGTERM ...)

我认为这样做的方法是使用 syscall.Exec 在 go 例程中启动节点服务器:

func launchCmd(path string, args []string) {
  err := syscall.Exec(path, args, os.Environ())
  if err != nil {
    panic(err)
  }
}

然后我想捕获由syscall 执行的命令生成的所有可能信号。我对 Go 很陌生,任何帮助将不胜感激。

【问题讨论】:

标签: go signals system-calls


【解决方案1】:

Go 中有三种执行程序的方式:

  1. syscallsyscall.Execsyscall.ForkExecsyscall.StartProcess 的包
  2. osos.StartProcess 一起打包
  3. os/exec 包与exec.Command

syscall.StartProcess 为低电平。它返回一个uintptr 作为句柄。

os.StartProcess 给你一个很好的os.Process 结构,你可以调用Signalos/exec 给你io.ReaderWriter 在管道上使用。两者都在内部使用syscall

读取您自己的进程以外的进程发送的信号似乎有点棘手。如果可能的话,syscall 可以做到。我在更高级别的包中看不到任何明显的东西。

要接收信号,您可以像这样使用signal.Notify

sigc := make(chan os.Signal, 1)
signal.Notify(sigc,
    syscall.SIGHUP,
    syscall.SIGINT,
    syscall.SIGTERM,
    syscall.SIGQUIT)
go func() {
    s := <-sigc
    // ... do something ...
}()

您只需要更改您有兴趣收听的信号即可。如果不指定信号,它将捕获所有可以捕获的信号。

您可以使用syscall.KillProcess.Signal 来映射信号。您可以从 Process.Pidsyscall.StartProcess 获取 pid。

【讨论】:

  • 谢谢,我会试试的。这个想法是让新贵监视这个包装器,它只会用于跟踪发生的事情
  • 好的,我可以捕获输入到程序的信号(例如,如果我使用 ^C),但无法获取系统调用执行的程序生成的信号。有什么想法吗?
  • @rmonjo 您正试图捕捉发送您的程序或的信号?
  • 我想捕获从我在syscall 中执行的程序发送的信号。我尝试了您的解决方案,当我使用 syscall.Exec 时,似乎该程序是分叉的,然后就退出了。但是,使用os/exec,我可以捕捉到诸如子退出之类的信号。
  • @rmonjo signal.Notify 捕获发送到您的程序的信号。捕捉可能有点棘手。细化回答。
【解决方案2】:

你可以使用signal.Notify

import (
"os"
"os/signal"
"syscall"
)

func main() {
    signalChannel := make(chan os.Signal, 2)
    signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)
    go func() {
        sig := <-signalChannel
        switch sig {
        case os.Interrupt:
            //handle SIGINT
        case syscall.SIGTERM:
            //handle SIGTERM
        }
    }()
    // ...
}

【讨论】:

  • 嗨,Baba,为什么要设置大小为 2 的缓冲通道?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多