吾八哥博客

您现在的位置是:首页 > 码农手记 > Golang > 正文

Golang

golang里捕获进程信号实现优雅退出的方法

吾八哥2018-07-21Golang9174

程序优雅退出可以更好的释放资源,或者打印一些重要的日志信息,在golang里可以实现捕获处理Signal信号来实现进程的优雅退出。

POSIX中定义的信号

POSIX.1-1990标准中定义的信号列表如下:

信号动作说明
SIGHUP1Term终端控制进程结束(终端连接断开)
SIGINT2Term用户发送INTR字符(Ctrl+C)触发
SIGQUIT3Core用户发送QUIT字符(Ctrl+/)触发
SIGILL4Core非法指令(程序错误、试图执行数据段、栈溢出等)
SIGABRT6Core调用abort函数触发
SIGFPE8Core算术运行错误(浮点运算错误、除数为零等)
SIGKILL9Term无条件结束程序(不能被捕获、阻塞或忽略)
SIGSEGV11Core无效内存引用(试图访问不属于自己的内存空间、对只读内存空间进行写操作)
SIGPIPE13Term消息管道损坏(FIFO/Socket通信时,管道未打开而进行写操作)
SIGALRM14Term时钟定时信号
SIGTERM15Term结束程序(可以被捕获、阻塞或忽略)
SIGUSR130,10,16Term用户保留
SIGUSR231,12,17Term用户保留
SIGCHLD20,17,18Ign子进程结束(由父进程接收)
SIGCONT19,18,25Cont继续执行已经停止的进程(不能被阻塞)
SIGSTOP17,19,23Stop停止进程(不能被捕获、阻塞或忽略)
SIGTSTP18,20,24Stop停止进程(可以被捕获、阻塞或忽略)
SIGTTIN21,21,26Stop后台程序从终端中读取数据时触发
SIGTTOU22,22,27Stop后台程序向终端中写数据时触发

golang里捕获Signal信号

Golang里使用signal.Notify可以接收的指定的信号,会用到os/signal包,具体实现代码为:

package main

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

func listenSignal() {
   sigs := make(chan os.Signal, 1)
   signal.Notify(sigs, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR1,
      syscall.SIGUSR2, syscall.SIGTSTP)
   select {
   case <-sigs:
      fmt.Println("exitapp,sigs:", sigs)
      os.Exit(0)
   }
}

func main() {
   fmt.Println("start...")
   go listenSignal()
   sum := 0
   for {
      sum++
      fmt.Println(sum)
      time.Sleep(time.Second)
   }
}

运行后按Ctrl+C或者调试环境下退出,均可以打印出"exitapp,sigs:xxx"。

docker里优雅退出golang程序

如果在docker关闭的时候要优雅的退出自己的程序,则在docker里程序的pid要为1才可以捕获到进程退出信号,我的做法是将自己的程序作为启动命令来启动。