go 语言 系统信号捕捉

go 语言 系统信号捕捉

信号类型

不同平台信号定义有所不同,通过命令 man signal 可获取各平台详细的信号介绍。

Go 中的 Signal 发送和处理

  • golang中对信号的处理主要使用os/signal包中的两个方法:
  • notify方法用来监听收到的信号
  • stop方法用来取消监听

监听全部信号

package main

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

// 监听全部信号
func main()  {
    //合建chan
    c := make(chan os.Signal)
    //监听所有信号
    signal.Notify(c)
    //阻塞直到有信号传入
    fmt.Println("启动")
    s := <-c
    fmt.Println("退出信号", s)
}

编译 go build example-1.go

启动 ./example-1

ctrl+c退出,输出 退出信号 interrupt

kill pid 输出 退出信号 terminated

监听指定信号

package main

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

// 监听指定信号
func main()  {
    //合建chan
    c := make(chan os.Signal)
    //监听指定信号 ctrl+c kill
    signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2)
    //阻塞直到有信号传入
    fmt.Println("启动")
    //阻塞直至有信号传入
    s := <-c
    fmt.Println("退出信号", s)
}

编译 go build example-2.go

启动 ./example-2

ctrl+c退出,输出 退出信号 interrupt

kill pid 输出 退出信号 terminated

kill -USR1 pid 输出 退出信号 user defined signal 1

kill -USR2 pid 输出 退出信号 user defined signal 2

优雅退出 go 守护进程

package main

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

// 优雅退出go守护进程
func main()  {
    //创建监听退出chan
    c := make(chan os.Signal)
    //监听指定信号 ctrl+c kill
    signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR1, syscall.SIGUSR2)
    go func() {
        for s := range c {
            switch s {
            case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
                fmt.Println("退出", s)
                ExitFunc()
            case syscall.SIGUSR1:
                fmt.Println("usr1", s)
            case syscall.SIGUSR2:
                fmt.Println("usr2", s)
            default:
                fmt.Println("other", s)
            }
        }
    }()

    fmt.Println("进程启动...")
    sum := 0
    for {
        sum++
        fmt.Println("sum:", sum)
        time.Sleep(time.Second)
    }
}

func ExitFunc()  {
    fmt.Println("开始退出...")
    fmt.Println("执行清理...")
    fmt.Println("结束退出...")
    os.Exit(0)
}

kill -USR1 pid 输出 usr1 user defined signal 1

kill -USR2 pid usr2 user defined signal 2

kill pid 退出 terminated 开始退出… 执行清理… 结束退出…

执行输出 go build example-3.go ./example-3

进程启动… sum: 1 sum: 2 sum: 3 sum: 4 sum: 5 sum: 6 sum: 7 sum: 8 sum: 9 usr1 user defined signal 1 sum: 10 sum: 11 sum: 12 sum: 13 sum: 14 usr2 user defined signal 2 sum: 15 sum: 16 sum: 17 退出 terminated 开始退出… 执行清理… 结束退出…