如何在 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 向它发送一些信号。