35

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

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

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

然后我想捕捉由syscall. 我对 Go 很陌生,任何帮助将不胜感激。

4

2 回答 2

61

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

  1. syscall与syscall.Execsyscall.ForkExecsyscall.StartProcess打包
  2. os使用os.StartProcess 打包
  3. os/exec使用exec.Command 打包

syscall.StartProcess是低级别的。它返回 auintptr作为句柄。

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来映射信号。您可以从syscall.StartProcessProcess.Pid或作为结果获取 pid 。

于 2013-08-07T15:04:51.263 回答
37

您可以使用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
        }
    }()
    // ...
}
于 2013-08-07T18:03:35.553 回答