专栏首页landv[golang]golang signal.Notify 信号,如何优雅的退出

[golang]golang signal.Notify 信号,如何优雅的退出

[golang]golang signal.Notify 信号,如何优雅的退出

golang 中的signal 包的Notify函数

函数声明为

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

官方描述:

Notify函数让signal包将输入信号转发到c。如果没有列出要传递的信号,会将所有输入信号传递到c;否则只传递列出的输入信号。

signal包不会为了向c发送信息而阻塞(就是说如果发送时c阻塞了,signal包会直接放弃):调用者应该保证c有足够的缓存空间可以跟上期望的信号频率。对使用单一信号用于通知的通道,缓存为1就足够了。 示例代码:

ch := make(chan os.Signal, 1)
    signal.Notify(ch, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGUSR1)
    for {
        s := <-ch
        switch s {
        case syscall.SIGQUIT:
            log.Infof("SIGSTOP")
            return
        case syscall.SIGSTOP:
            log.Infof("SIGSTOP")
            return
        case syscall.SIGHUP:
            log.Infof("SIGHUP")
            return
        case syscall.SIGKILL:
            log.Infof("SIGKILL")
            return
        case syscall.SIGUSR1:
            log.Infof("SIGUSR1")
            return
        default:
            log.Infof("default")
            return
        }
    }

以上代码告诉 signal ,将对应的信号通知 ch,然后在 for 循环中针对不同信号做不同的处理, for 循环为死循环。

优雅退出go守护进程

package main
 
import (
        "fmt"
        "os"
        "os/signal"
        "syscall"
        "time"
)
 
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("Program Exit...", s)
                                GracefullExit()
                        case syscall.SIGUSR1:
                                fmt.Println("usr1 signal", s)
                        case syscall.SIGUSR2:
                                fmt.Println("usr2 signal", s)
                        default:
                                fmt.Println("other signal", s)
                        }
                }
        }()
 
        fmt.Println("Program Start...")
        sum := 0
        for {
                sum++
                fmt.Println("sum:", sum)
                time.Sleep(time.Second)
        }
}
 
func GracefullExit() {
        fmt.Println("Start Exit...")
        fmt.Println("Execute Clean...")
        fmt.Println("End Exit...")
        os.Exit(0)
}

Linux Signal及Golang中的信号处理

信号(Signal)是Linux, 类Unix和其它POSIX兼容的操作系统中用来进程间通讯的一种方式。一个信号就是一个异步的通知,发送给某个进程,或者同进程的某个线程,告诉它们某个事件发生了。 当信号发送到某个进程中时,操作系统会中断该进程的正常流程,并进入相应的信号处理函数执行操作,完成后再回到中断的地方继续执行。 如果目标进程先前注册了某个信号的处理程序(signal handler),则此处理程序会被调用,否则缺省的处理程序被调用。

https://colobu.com/2015/10/09/Linux-Signals/

信号类型

个平台的信号定义或许有些不同。下面列出了POSIX中定义的信号。 Linux 使用34-64信号用作实时系统中。 命令man 7 signal提供了官方的信号介绍。

在POSIX.1-1990标准中定义的信号列表

信号

动作

说明

SIGHUP

1

Term

终端控制进程结束(终端连接断开)

SIGINT

2

Term

用户发送INTR字符(Ctrl+C)触发

SIGQUIT

3

Core

用户发送QUIT字符(Ctrl+/)触发

SIGILL

4

Core

非法指令(程序错误、试图执行数据段、栈溢出等)

SIGABRT

6

Core

调用abort函数触发

SIGFPE

8

Core

算术运行错误(浮点运算错误、除数为零等)

SIGKILL

9

Term

无条件结束程序(不能被捕获、阻塞或忽略)

SIGSEGV

11

Core

无效内存引用(试图访问不属于自己的内存空间、对只读内存空间进行写操作)

SIGPIPE

13

Term

消息管道损坏(FIFO/Socket通信时,管道未打开而进行写操作)

SIGALRM

14

Term

时钟定时信号

SIGTERM

15

Term

结束程序(可以被捕获、阻塞或忽略)

SIGUSR1

30,10,16

Term

用户保留

SIGUSR2

31,12,17

Term

用户保留

SIGCHLD

20,17,18

Ign

子进程结束(由父进程接收)

SIGCONT

19,18,25

Cont

继续执行已经停止的进程(不能被阻塞)

SIGSTOP

17,19,23

Stop

停止进程(不能被捕获、阻塞或忽略)

SIGTSTP

18,20,24

Stop

停止进程(可以被捕获、阻塞或忽略)

SIGTTIN

21,21,26

Stop

后台程序从终端中读取数据时触发

SIGTTOU

22,22,27

Stop

后台程序向终端中写数据时触发

在SUSv2和POSIX.1-2001标准中的信号列表:

信号

动作

说明

SIGTRAP

5

Core

Trap指令触发(如断点,在调试器中使用)

SIGBUS

0,7,10

Core

非法地址(内存地址对齐错误)

SIGPOLL

Term

Pollable event (Sys V). Synonym for SIGIO

SIGPROF

27,27,29

Term

性能时钟信号(包含系统调用时间和进程占用CPU的时间)

SIGSYS

12,31,12

Core

无效的系统调用(SVr4)

SIGURG

16,23,21

Ign

有紧急数据到达Socket(4.2BSD)

SIGVTALRM

26,26,28

Term

虚拟时钟信号(进程占用CPU的时间)(4.2BSD)

SIGXCPU

24,24,30

Core

超过CPU时间资源限制(4.2BSD)

SIGXFSZ

25,25,31

Core

超过文件大小资源限制(4.2BSD)

Windows中没有SIGUSR1,可以用SIGBREAK或者SIGINT代替。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [CodeIgniter4]-利用配置文件开始工作

    每一个项目,都需要一种方法来定义不同的全局配置项,而这通常是借助配置文件来实现的。 而配置文件,一般来说,是通过声明一个将所有的配置项作为公开属性的类,来实现这...

    landv
  • win 8.1_64 安装usb 转串口驱动

    landv
  • php归档格式:phar文件详解(创建、使用、解包还原提取)

    landv
  • 腾讯高校合作中心实习生招募

    ? 腾讯高校合作中心 为了与高校/科研机构合作推动信息科学技术创新,培养互联网顶级人才,营造互联网产业健康生态,腾讯围绕科研合作、人才培养、学术交流三条主线开...

    腾讯高校合作
  • 记一次远程命令执行漏洞的挖掘过程

    最近为甲方做渗透测试发现了一个远程命令执行漏洞,可以通过恶意参数传递执行bash命令,本文回顾一下漏洞的挖掘过程。

    FB客服
  • Druid入门(1)—— 快速入门实时分析利器-Druid_0.17

    http://druid.io/现在也会跳转https://druid.apache.org/

    实时计算
  • iOS设置tableViewCell之间的间距(去掉UItableview headerview黏性)

    王大锤
  • ZooKeeper Java API

    ZooKeeper API 的核心部分是 ZooKeeper 类。在构造函数中提供一些参数来连接 ZooKeeper,并提供如下方法:

    smartsi
  • Excel 的10个神奇功能,你会用几个?

    导读:在很多人的眼里,Excel只是一个简单的表格工具,大不了可以进行求和等简单的计算,他们这样认为我不怪他们,因为他们根本不了解Excel的神奇作用。

    华章科技
  • MongoDB-4 GridFS 文件存储

    风间影月

扫码关注云+社区

领取腾讯云代金券