go 监听系统信号

linux 信号查看

kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

go 标准库里提供了 signal.Notify 来获取系统信号,函数原型以下:linux

func Notify(c chan<- os.Signal, sig ...os.Signal)

Notify函数让signal包将输入信号转发到c。若是没有列出要传递的信号,会将全部输入信号传递到c;不然只传递列出的输入信号。
signal包不会为了向c发送信息而阻塞(就是说若是发送时c阻塞了,signal包会直接放弃):
调用者应该保证c有足够的缓存空间能够跟上指望的信号频率。对使用单一信号用于通知的通道,缓存为1就足够了。shell

能够使用同一通道屡次调用Notify:每一次都会扩展该通道接收的信号集。惟一从信号集去除信号的方法是调用Stop。
能够使用同一信号和不一样通道屡次调用Notify:每个通道都会独立接收到该信号的一个拷贝。缓存

实践

咱们能够起一个 goroutine 来监听系统信号, 一个 channel 获取系统信号,另外一个 channel 来控制程序的退出。函数

示例代码以下:code

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    exitChan := make(chan int)
    signalChan := make(chan os.Signal, 1)
    go func() {
        <-signalChan
        fmt.Println("signal received")
        exitChan <- 1
    }()
    signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
    <-exitChan
}