我想在 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 中有三种执行程序的方式:
syscall
包含 syscall.Exec、syscall.ForkExec、syscall.StartProcessos
带有 os.StartProcessos/exec
包含 exec.Commandsyscall.StartProcess 是低级别。它返回一个
uintptr
作为句柄。
os.StartProcess
为您提供了一个不错的 os.Process
结构,您可以在其上调用 Signal。 os/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.Kill 或 Process.Signal 来映射信号。您可以从 Process.Pid
或从
syscall.StartProcess获取 pid。
:
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
}
}()
// ...
}
go run main.go
独立构建和运行它:
go build main.go
./main