如何在 Go 中捕获任意 UNIX 信号
How to capture arbitrary UNIX signals in Go
我可以在 signal package but how can I capture signals from 34 (SIGRTMIN) to 64 (SIGRTMAX) inclusively (link) 中捕获信号吗? Golang 将它们称为“信号 34”、“信号 64”等,但这超出了重点。当我 运行 "pkill -34" 我希望我的应用程序注意到它。
当我捕获所有信号时,我可以捕获它们:
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan)
但是我不想捕获所有信号,我只想要我之前提到的信号。
我也知道我可以捕获像这样的单个信号:
signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)
但这需要信号常量,而我找不到与我想要捕获的信号相对应的常量。有什么想法吗?
简答:
您可以将新信号声明为 syscall.Signal
:
类型的常量
const (
SIGRTMIN = syscall.Signal(0x22)
)
长答案(如何运作):
signal.Notify
函数签名是:
Notify(c chan<- os.Signal, sig ...os.Signal)
其中 os.Signal
是这样定义的接口:
// A Signal represents an operating system signal.
// The usual underlying implementation is operating system-dependent:
// on Unix it is syscall.Signal.
type Signal interface {
String() string
Signal() // to distinguish from other Stringers
}
通常您会像示例中那样使用 signal.Notify
函数:
signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)
所以如果我们检查 syscall
包中那些常量的实现,我们会看到:
SIGKILL = Signal(0x9)
syscall
包中的这个 Signal
是定义的类型:
// A Signal is a number describing a process signal.
// It implements the os.Signal interface.
type Signal int
func (s Signal) Signal() {}
func (s Signal) String() string {
// ... a few lines of code
}
它只是一个底层 int
,带有无操作 Signal()
方法和 Stringer 实现。
因此,您可以通过转换任意 int
值,以相同的方式为要捕获的信号声明自己的常量:
const (
SIGRTMIN = syscall.Signal(0x22)
)
signal.Notify(sigChan, SIGRTMIN, /* etc. */)
------------------------答案------------ --------------
由于 [blackgreen][3],此问题已得到解决。
我做了一个小片段来轻松捕获所有 SIGRT 信号:
package main
import (
"fmt"
"syscall"
"os/signal"
"os"
)
func getSIGRTchannel() chan os.Signal {
sigChan := make(chan os.Signal, 1)
sigArr := make([]os.Signal, 31)
for i := range sigArr {
sigArr[i] = syscall.Signal(i + 0x22)
}
signal.Notify(sigChan, sigArr...)
return sigChan
}
func main() {
c := getSIGRTchannel()
// Block until a signal is received.
for {
s := <-c
fmt.Println("Got signal:", s)
}
}
要玩它,运行 这个程序在一个终端 window 并从另一个终端 window 向它发送一些信号。
我可以在 signal package but how can I capture signals from 34 (SIGRTMIN) to 64 (SIGRTMAX) inclusively (link) 中捕获信号吗? Golang 将它们称为“信号 34”、“信号 64”等,但这超出了重点。当我 运行 "pkill -34" 我希望我的应用程序注意到它。
当我捕获所有信号时,我可以捕获它们:
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan)
但是我不想捕获所有信号,我只想要我之前提到的信号。
我也知道我可以捕获像这样的单个信号:
signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)
但这需要信号常量,而我找不到与我想要捕获的信号相对应的常量。有什么想法吗?
简答:
您可以将新信号声明为 syscall.Signal
:
const (
SIGRTMIN = syscall.Signal(0x22)
)
长答案(如何运作):
signal.Notify
函数签名是:
Notify(c chan<- os.Signal, sig ...os.Signal)
其中 os.Signal
是这样定义的接口:
// A Signal represents an operating system signal.
// The usual underlying implementation is operating system-dependent:
// on Unix it is syscall.Signal.
type Signal interface {
String() string
Signal() // to distinguish from other Stringers
}
通常您会像示例中那样使用 signal.Notify
函数:
signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)
所以如果我们检查 syscall
包中那些常量的实现,我们会看到:
SIGKILL = Signal(0x9)
syscall
包中的这个 Signal
是定义的类型:
// A Signal is a number describing a process signal.
// It implements the os.Signal interface.
type Signal int
func (s Signal) Signal() {}
func (s Signal) String() string {
// ... a few lines of code
}
它只是一个底层 int
,带有无操作 Signal()
方法和 Stringer 实现。
因此,您可以通过转换任意 int
值,以相同的方式为要捕获的信号声明自己的常量:
const (
SIGRTMIN = syscall.Signal(0x22)
)
signal.Notify(sigChan, SIGRTMIN, /* etc. */)
------------------------答案------------ --------------
由于 [blackgreen][3],此问题已得到解决。
我做了一个小片段来轻松捕获所有 SIGRT 信号:
package main
import (
"fmt"
"syscall"
"os/signal"
"os"
)
func getSIGRTchannel() chan os.Signal {
sigChan := make(chan os.Signal, 1)
sigArr := make([]os.Signal, 31)
for i := range sigArr {
sigArr[i] = syscall.Signal(i + 0x22)
}
signal.Notify(sigChan, sigArr...)
return sigChan
}
func main() {
c := getSIGRTchannel()
// Block until a signal is received.
for {
s := <-c
fmt.Println("Got signal:", s)
}
}
要玩它,运行 这个程序在一个终端 window 并从另一个终端 window 向它发送一些信号。