Golang捕获信号

I want to implement a "process wrapper" in Go. Basically what it will do, is launch a process (lets say a node server) and monitor it (catch signals like SIGKILL, SIGTERM ...)

I think the way to do is to launch the node server in a go routine using syscall.Exec:

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

Then I'd like to catch every possible signals generated by the command executed by syscall. I'm pretty new to Go, any help would be appreciated.

There are three ways of executing a program in Go:

  1. syscall package with syscall.Exec, syscall.ForkExec, syscall.StartProcess
  2. os package with os.StartProcess
  3. os/exec package with exec.Command

syscall.StartProcess is low level. It returns a uintptr as a handle.

os.StartProcess gives you a nice os.Process struct that you can call Signal on. os/exec gives you io.ReaderWriter to use on a pipe. Both use syscall internally.

Reading signals sent from a process other than your own seems a bit tricky. If it was possible, syscall would be able to do it. I don't see anything obvious in the higher level packages.

To receive a signal you can use signal.Notify like this:

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

You just need to change the signals you're interested in listening to. If you don't specify a signal, it'll catch all the signals that can be captured.

You would use syscall.Kill or Process.Signal to map the signal. You can get the pid from Process.Pid or as a result from syscall.StartProcess.

You can use 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
        }
    }()
    // ...
}