[signals] “지연”방식으로 Ctrl + C 신호를 캡처하고 정리 기능을 실행할 수 있습니까?

콘솔에서 보낸 Ctrl+C( SIGINT) 신호 를 캡처하고 부분 실행 합계를 인쇄하고 싶습니다 .

골랑에서 가능합니까?

참고 : 내가 먼저 질문을 게시 할 때 나는에 대해 혼란스러워했다 Ctrl+C되는 SIGTERM대신 SIGINT.



답변

os / signal 패키지를 사용하여 들어오는 신호를 처리 할 수 있습니다 . Ctrl+ CSIGINT 이므로이를 사용하여 트랩 할 수 있습니다 os.Interrupt.

c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func(){
    for sig := range c {
        // sig is a ^C, handle it
    }
}()

프로그램을 종료하고 정보를 인쇄하는 방식은 전적으로 귀하에게 달려 있습니다.


답변

이것은 작동합니다 :

package main

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

func cleanup() {
    fmt.Println("cleanup")
}

func main() {
    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-c
        cleanup()
        os.Exit(1)
    }()

    for {
        fmt.Println("sleeping...")
        time.Sleep(10 * time.Second) // or runtime.Gosched() or similar per @misterbee
    }
}


답변

다른 답변에 약간 더하기 위해 실제로 SIGTERM (kill 명령으로 전송 된 기본 신호)을 잡으려면 syscall.SIGTERMos.Interrupt 대신 사용할 수 있습니다 . syscall 인터페이스는 시스템에 따라 다르며 모든 곳에서 작동하지 않을 수 있습니다 (예 : Windows). 그러나 두 가지를 모두 잘 잡을 수 있습니다.

c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
....


답변

위의 허용 된 답변에 하나 또는 두 개의 작은 오타가 있었으므로 여기에 정리 된 버전이 있습니다. 이 예에서는 Ctrl+를 수신 할 때 CPU 프로파일 러를 중지합니다 C.

// capture ctrl+c and stop CPU profiler                            
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
  for sig := range c {
    log.Printf("captured %v, stopping profiler and exiting..", sig)
    pprof.StopCPUProfile()
    os.Exit(1)
  }
}()    


답변

위의 모든 내용은 접속했을 때 작동하는 것처럼 보이지만 gobyexample의 신호 페이지 에는 신호를 캡처하는 데 대한 깨끗하고 완전한 예가 있습니다. 이 목록에 추가 할 가치가 있습니다.


답변

Death 는 채널과 대기 그룹을 사용하여 종료 신호를 기다리는 간단한 라이브러리입니다. 신호가 수신되면 정리하려는 모든 구조체에서 close 메소드를 호출합니다.


답변

당신은 syscall.SIGINT 및 syscall.SIGTERM 신호를 감지하는 다른 goroutine을 가지고 사용 채널로 중계 할 수 signal.Notify을 . 채널을 사용하여 해당 고 루틴에 후크를 보내고 함수 슬라이스에 저장할 수 있습니다. 채널에서 종료 신호가 감지되면 슬라이스에서 해당 기능을 실행할 수 있습니다. 자원을 정리하고 실행중인 goroutines가 완료 될 때까지 기다리거나 데이터를 유지하거나 부분 실행 합계를 인쇄하는 데 사용할 수 있습니다.

종료시 후크를 추가하고 실행하는 작고 간단한 유틸리티를 작성했습니다. 도움이 되길 바랍니다.

https://github.com/ankit-arora/go-utils/blob/master/go-shutdown-hook/shutdown-hook.go

이를 ‘지연’방식으로 수행 할 수 있습니다.

서버를 정상적으로 종료하는 예 :

srv := &http.Server{}

go_shutdown_hook.ADD(func() {
    log.Println("shutting down server")
    srv.Shutdown(nil)
    log.Println("shutting down server-done")
})

l, err := net.Listen("tcp", ":3090")

log.Println(srv.Serve(l))

go_shutdown_hook.Wait()