Ich möchte das von der Konsole gesendete Ctrl+C( SIGINT
) Signal erfassen und einige Teillaufsummen ausdrucken.
Ist das in Golang möglich?
Hinweis: Als ich die Frage zum ersten Mal stellte, war ich verwirrt darüber Ctrl+C, SIGTERM
statt zu sein SIGINT
.
for sig := range g {
können Sie auch<-sigchan
wie in dieser vorherigen Antwort verwenden: stackoverflow.com/questions/8403862/…go run
eine Konsole ausführen und ein SIGTERM über ^ C senden, wird das Signal in den Kanal geschrieben und das Programm antwortet, scheint jedoch unerwartet aus der Schleife auszusteigen. Dies liegt daran, dass das SIGRERM auch gehtgo run
! (Dies hat mich erheblich verwirrt!)runtime.Gosched
an einer geeigneten Stelle aufrufen muss (in der Hauptschleife Ihres Programms, falls vorhanden), damit die Goroutine eine Prozessorzeit erhält, um das Signal zu verarbeitenDas funktioniert:
quelle
Um die anderen Antworten etwas zu ergänzen, können Sie
syscall.SIGTERM
anstelle von os.Interrupt SIGTERM (das vom Befehl kill gesendete Standardsignal) abfangen. Beachten Sie, dass die Syscall-Schnittstelle systemspezifisch ist und möglicherweise nicht überall funktioniert (z. B. unter Windows). Aber es funktioniert gut, beides zu fangen:quelle
signal.Notify
Funktion können mehrere Signale gleichzeitig angegeben werden. So können Sie Ihren Code vereinfachensignal.Notify(c, os.Interrupt, syscall.SIGTERM)
.os.Kill
entspricht aufsyscall.Kill
, das ein Signal ist , das aber nicht gefangen versandt werden kann. Es entspricht dem Befehlkill -9 <pid>
. Wenn Sie fangenkill <pid>
und ordnungsgemäß herunterfahren möchten , müssen Sie verwendensyscall.SIGTERM
.Die oben akzeptierte Antwort enthielt (zum Zeitpunkt der Veröffentlichung) ein oder zwei kleine Tippfehler. Hier ist also die bereinigte Version. In diesem Beispiel stoppe ich den CPU-Profiler beim Empfang von Ctrl+ C.
quelle
runtime.Gosched
an einer geeigneten Stelle aufrufen muss (in der Hauptschleife Ihres Programms, falls vorhanden), damit die Goroutine eine Prozessorzeit erhält, um das Signal zu verarbeitenAlle oben genannten Punkte scheinen zu funktionieren, wenn sie zusammengefügt werden, aber die Signalseite von gobyexample enthält ein wirklich sauberes und vollständiges Beispiel für die Signalerfassung. Es lohnt sich, diese Liste zu ergänzen.
quelle
Death ist eine einfache Bibliothek, die Kanäle und eine Wartegruppe verwendet, um auf Abschaltsignale zu warten. Sobald das Signal empfangen wurde, ruft es eine close-Methode für alle Ihre Strukturen auf, die Sie bereinigen möchten.
quelle
Sie können eine andere Goroutine verwenden, die syscall.SIGINT- und syscall.SIGTERM-Signale erkennt und diese mithilfe von signal.Notify an einen Kanal weiterleitet . Sie können einen Hook über einen Kanal an diese Goroutine senden und in einem Funktions-Slice speichern. Wenn das Abschaltsignal auf dem Kanal erkannt wird, können Sie diese Funktionen im Slice ausführen. Dies kann verwendet werden, um die Ressourcen zu bereinigen, auf das Ausführen von Goroutinen zu warten, Daten beizubehalten oder Teillaufsummen zu drucken.
Ich habe ein kleines und einfaches Dienstprogramm geschrieben, um beim Herunterfahren Hooks hinzuzufügen und auszuführen. Hoffe es kann hilfreich sein.
https://github.com/ankit-arora/go-utils/blob/master/go-shutdown-hook/shutdown-hook.go
Sie können dies auf eine "verzögerte" Weise tun.
Beispiel für das ordnungsgemäße Herunterfahren eines Servers:
quelle
Dies ist eine andere Version, die funktioniert, wenn Sie einige Aufgaben bereinigen müssen. Der Code verlässt den Bereinigungsprozess in seiner Methode.
Wenn Sie die Hauptfunktion bereinigen müssen, müssen Sie das Signal im Hauptthread auch mit go func () erfassen.
quelle
Nur zur Veranschaulichung, wenn jemand eine Möglichkeit benötigt, Signale unter Windows zu verarbeiten. Ich hatte die Anforderung, von Prog A, das Prog B aufruft, über OS / Exec zu kommen, aber Prog B konnte nie ordnungsgemäß beendet werden, da Signale über Ex gesendet wurden. cmd.Process.Signal (syscall.SIGTERM) oder andere Signale werden unter Windows nicht unterstützt. Ich habe damit umgegangen, indem ich eine temporäre Datei als Signal erstellt habe. .signal.term durch Prog A und Prog B muss überprüfen, ob diese Datei auf Intervallbasis vorhanden ist. Wenn eine Datei vorhanden ist, wird das Programm beendet und bei Bedarf bereinigt. Ich bin sicher, dass es andere Möglichkeiten gibt, aber dies hat den Job erledigt.
quelle