英文:
Golang catch signals
问题
我想在Go语言中实现一个"进程包装器"。基本上它的功能是启动一个进程(比如一个Node服务器)并监控它(捕获诸如SIGKILL、SIGTERM等信号)。
我认为可以通过在一个Go协程中使用syscall.Exec
来启动Node服务器:
func launchCmd(path string, args []string) {
err := syscall.Exec(path, args, os.Environ())
if err != nil {
panic(err)
}
}
然后,我想捕获syscall
执行的命令生成的所有可能的信号。我对Go还不太熟悉,希望能得到帮助。
英文:
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.
答案1
得分: 71
在Go语言中,有三种执行程序的方式:
- 使用
syscall
包的syscall.Exec、syscall.ForkExec和syscall.StartProcess方法。 - 使用
os
包的os.StartProcess方法。 - 使用
os/exec
包的exec.Command方法。
syscall.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
// ... 做一些操作 ...
}()
只需更改您感兴趣的信号即可。如果不指定信号,它将捕获所有可捕获的信号。
您可以使用syscall.Kill或Process.Signal方法发送信号。可以从Process.Pid
或syscall.StartProcess的结果中获取进程ID。
英文:
There are three ways of executing a program in Go:
syscall
package with syscall.Exec, syscall.ForkExec, syscall.StartProcessos
package with os.StartProcessos/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.
答案2
得分: 39
你可以使用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:
//处理 SIGINT
case syscall.SIGTERM:
//处理 SIGTERM
}
}()
// ...
}
英文:
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
}
}()
// ...
}
答案3
得分: 1
func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT, syscall.SIGSEGV)
for {
s := <-c
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
return
case syscall.SIGHUP:
case syscall.SIGSEGV:
default:
return
}
}
}
这是一个Go语言的代码片段。它创建了一个通道c
,并使用signal.Notify
函数将一些系统信号(SIGHUP、SIGQUIT、SIGTERM、SIGINT、SIGSEGV)发送到通道c
中。然后,通过一个无限循环,从通道c
中接收信号s
,并根据不同的信号进行处理。如果接收到的信号是SIGQUIT、SIGTERM或SIGINT,程序将返回;如果接收到的信号是SIGHUP或SIGSEGV,程序将继续执行;否则,程序也将返回。
英文:
func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT, syscall.SIGSEGV)
for {
s := <-c
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
return
case syscall.SIGHUP:
case syscall.SIGSEGV:
default:
return
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论