美文网首页
【Golang】信号处理

【Golang】信号处理

作者: JinMoon | 来源:发表于2019-08-18 18:59 被阅读0次

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

    Notify函数

    原型:

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

    说明:

    该函数会将进程收到的系统Signal转发给channel c,转发哪些信号由该函数的可变参数决定,如果你没有传入sig参数,那么Notify会将系统收到的所有信号转发给c。

    使用:

    1.监听全部信号

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

    2.监听指定信号

    c := make(chan os.Signal)
    signal.Notify(c, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2)
    

    则Go只会关注你传入的Signal类型,其他Signal将会按照默认方式处理,大多都是进程退出。

    因此你需要在Notify中传入你要关注和处理的Signal类型,也就是拦截它们,提供自定义处理函数来改变它们的行为。

    3.优雅退出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)
    }
    
    注意:
    1. chan os.Signal 一般是带缓冲的(不带也行),缓冲大小一般设置为和监听信号种类一致,这样被监听信号的重复递达可能会丢失信号(不确定)。

    相关文章

      网友评论

          本文标题:【Golang】信号处理

          本文链接:https://www.haomeiwen.com/subject/phkdsctx.html