Ich möchte das einfangen Ctrl+C Das Signal (SIGINT
) wird von der Konsole gesendet und gibt einige Teillaufsummen aus.
Ist das in Golang möglich?
Hinweis: Als ich die Frage zum ersten Mal gepostet habe, war ich verwirrt Ctrl+C SIGTERM
anstelle von SIGINT
sein.
Sie können das Paket os/signal verwenden, um eingehende Signale zu verarbeiten. ^ C ist SIGINT , damit können Sie os.Interrupt
abfangen.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func(){
for sig := range c {
// sig is a ^C, handle it
}
}()
Die Art und Weise, wie Sie Ihr Programm dazu bringen, Informationen zu beenden und Informationen auszudrucken, liegt ganz bei Ihnen.
Das funktioniert:
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
}
}
Um etwas zu den anderen Antworten hinzuzufügen, wenn Sie SIGTERM (das durch den Kill-Befehl gesendete Standardsignal) tatsächlich abrufen möchten, können Sie syscall.SIGTERM
anstelle von os.Interrupt verwenden. Beachten Sie, dass die Syscall-Schnittstelle systemspezifisch ist und möglicherweise nicht überall funktioniert (z. B. unter Windows). Aber es funktioniert gut, um beide zu fangen:
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
....
Es gab (zum Zeitpunkt der Veröffentlichung) ein oder zwei kleine Tippfehler in der oben akzeptierten Antwort, daher hier die aufgeräumte Version. In diesem Beispiel stoppe ich den CPU-Profiler, wenn Ctrl + C empfangen wird.
// 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)
}
}()
Alle oben genannten Funktionen scheinen beim Zusammenfügen zu funktionieren, aber auf der Signalseite von gobyexample gibt es ein wirklich sauberes und vollständiges Beispiel für die Signalerfassung. Es lohnt sich, diese Liste hinzuzufügen.
Dies ist eine andere Version, die funktioniert, falls Sie einige Aufgaben bereinigen müssen. Code hinterlässt in seiner Methode einen Bereinigungsprozess.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
_,done1:=doSomething1()
_,done2:=doSomething2()
//do main thread
println("wait for finish")
<-done1
<-done2
fmt.Print("clean up done, can exit safely")
}
func doSomething1() (error, chan bool) {
//do something
done:=make(chan bool)
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
//cleanup of something1
done<-true
}()
return nil,done
}
func doSomething2() (error, chan bool) {
//do something
done:=make(chan bool)
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
//cleanup of something2
done<-true
}()
return nil,done
}
falls Sie die Hauptfunktion bereinigen müssen, müssen Sie auch das Signal im Haupt-Thread mit go func () erfassen.