2013-08-07 120 views
9

我想在Go中实现一个“流程包装器”。基本上它会做什么,是启动一个进程(可以说一个节点服务器)并监控它(捕获信号像SIGKILL,SIGTERM ...)Golang捕获信号

我认为做的方法是启动节点服务器常规使用syscall.Exec

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

然后我想捕捉由syscall执行该命令产生的每个可能的信号。我对Go很新,任何帮助将不胜感激。

+0

[参见](http://stackoverflow.com/q/11268943/720999)。 – kostix

回答

30

有围棋执行程序的方式有三种:

  1. syscallsyscall.Execsyscall.ForkExecsyscall.StartProcess
  2. osos.StartProcess
  3. os/execexec.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。

+0

Thx我会尝试。这个想法是让这个包装被暴发户监控,它只会被用来跟踪发生了什么 – rmonjo

+0

好吧,我可以捕获输入到程序中的信号(例如,如果我做^ C例如)但不能产生信号由我的程序由系统调用执行。任何想法 ? – rmonjo

+0

@rmonjo你试图捕获从你的程序发送*到*发送的信号吗? – Luke

16

您可以使用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 
     } 
    }() 
    // ... 
}