Skip to content

接收系统信号 #55

@kevinyan815

Description

@kevinyan815

有时,我们希望 Go 程序能够智能地处理 Unix 系统信号。例如,我们可能希望服务器在收到 SIGTERM 时做清理操作,处理完已接收的请求后正常关闭,或者让命令行工具在收到 SIGINT 信号时停止处理输入。下面会演示在 Go 程序里通过 channel中处理信号的方法。

package main

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

func main() {

    sigs := make(chan os.Signal)
    done := make(chan bool)

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
    }()

    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}

Go 信号通知通过在Channel上发送 os.Signal 信号值来工作。通过make(chan os.Signal)创建一个接收系统信号的通道,signal.Notify将创建的通道进行注册,让其能够接收到后面参数指定的类型的系统信号。

下面是一个通过监听SIGTERM信号,优雅关停 gRPC Server的例子:

func main() {

   // ...

   errChan := make(chan error)
   stopChan := make(chan os.Signal)

   // bind OS events to the signal channel
   signal.Notify(stopChan, syscall.SIGTERM, syscall.SIGINT)

   // run blocking call in a separate goroutine, report errors via channel
   go func() {
        if err := grpcServer.Serve(lis); err != nil {
            errChan <- err
        }
    }()

   // terminate your environment gracefully before leaving main function
   defer func() {
      closeDbConnections()
   }()

   // block until either OS signal, or server fatal error
   select {
      case err := <-errChan:
          log.Printf("Fatal error: %v\n", err) 
      case <-stopChan:
          server.GracefulStop()
   }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions