是否有可能以“延迟”方式捕获Ctrl + C信号并运行清理function?

我想捕获从控制台发送的Ctrl + CSIGINT )信号,并打印出部分运行总数。

Golang可能吗?

注意:当我第一次发布这个问题时,我很困惑Ctrl + CSIGTERM而不是SIGINT

您可以使用os / signal包来处理input信号。 ^ C是SIGINT ,所以你可以用它来捕获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, 2) 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.SIGTERM代替os.Interrupt。 注意,系统调用接口是系统特定的,可能无法在任何地方工作(例如在Windows上)。 但它很好地捕捉到两者:

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

在上面接受的答案中有(在发布的时候)一个或两个小的错别字,所以这里是清理的版本。 在这个例子中,我在接收Ctrl + C时停止CPU分析器。

 // 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的信号页面却是一个非常干净和完整的信号捕捉示例。 值得添加到这个列表。

死亡是一个简单的库,它使用频道和一个等待组来等待关机信号。 一旦收到信号,它就会调用你想要清理的所有结构的close方法。

你可以有一个不同的goroutine来检测syscall.SIGINT和syscall.SIGTERM信号,并用signal.Notify把它们转发到一个通道。 您可以使用通道向该goroutine发送一个钩子并将其保存在一个function片中。 在通道上检测到closures信号时,可以执行切片中的这些function。 这可用于清理资源,等待运行goroutines完成,保留数据或打印部分运行总计。

我写了一个小而简单的工具来在关机时添加和运行挂钩。 希望它可以帮助。

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

你可以用“延迟”的方式来做到这一点。

优雅地closures服务器的示例:

 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() 

只是为了logging如果有人需要一种方式来处理Windows上的信号。 我有一个需要处理从PROG一个调用PROG B通过OS / EXEC,但PROG B从来没有能够正常终止,因为通过前发送信号。 Windows上不支持cmd.Process.Signal(syscall.SIGTERM)或其他信号。 我处理的方式是创build一个临时文件作为信号ex。 .signal.term通过prog A和prog B需要检查该文件是否存在于间隔基础上,如果文件存在,它将退出程序并在需要时处理清理,我相信还有其他方法,但是这样做的工作。