Je veux capturer le signal Ctrl+C( SIGINT
) envoyé depuis la console et imprimer des totaux partiels.
Est-ce possible à Golang?
Note: Quand je suis posté la question que je confus au sujet d' Ctrl+Cêtre au SIGTERM
lieu de SIGINT
.
Vous pouvez utiliser le package os / signal pour gérer les signaux entrants. Ctrl+ Cest SIGINT , vous pouvez donc l'utiliser pour intercepter 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
}
}()
La manière dont vous faites interrompre votre programme et imprimer des informations vous appartient entièrement.
for sig := range g {
, vous pouvez également utiliser<-sigchan
comme dans cette réponse précédente: stackoverflow.com/questions/8403862/…go run
dans une console et envoyez un SIGTERM via ^ C, le signal est écrit dans le canal et le programme répond, mais semble sortir de la boucle de manière inattendue. C'est parce que le SIGRERM vago run
aussi! (Cela m'a causé beaucoup de confusion!)runtime.Gosched
à un endroit approprié (dans la boucle principale de votre programme, s'il en a un)Cela marche:
la source
Pour ajouter un peu aux autres réponses, si vous voulez réellement attraper SIGTERM (le signal par défaut envoyé par la commande kill), vous pouvez utiliser
syscall.SIGTERM
à la place de os.Interrupt. Attention, l'interface syscall est spécifique au système et peut ne pas fonctionner partout (par exemple sur Windows). Mais cela fonctionne bien pour attraper les deux:la source
signal.Notify
fonction permet de spécifier plusieurs signaux à la fois. Ainsi, vous pouvez simplifier votre code ensignal.Notify(c, os.Interrupt, syscall.SIGTERM)
.os.Kill
correspond àsyscall.Kill
, qui est un signal qui peut être envoyé mais pas capté. Son équivalent à la commandekill -9 <pid>
. Si vous voulez intercepterkill <pid>
et arrêter gracieusement, vous devez utilisersyscall.SIGTERM
.Il y avait (au moment de la publication) une ou deux petites fautes de frappe dans la réponse acceptée ci-dessus, alors voici la version nettoyée. Dans cet exemple, j'arrête le profileur de processeur lors de la réception de Ctrl+ C.
la source
runtime.Gosched
à un endroit approprié (dans la boucle principale de votre programme, s'il en a un)Tous les éléments ci-dessus semblent fonctionner lorsqu'ils sont épissés, mais la page des signaux de gobyexample propose un exemple vraiment propre et complet de capture de signal. Vaut la peine d'être ajouté à cette liste.
la source
Death est une bibliothèque simple qui utilise des canaux et un groupe d'attente pour attendre les signaux d'arrêt. Une fois le signal reçu, il appellera une méthode close sur toutes vos structures que vous souhaitez nettoyer.
la source
Vous pouvez avoir une goroutine différente qui détecte les signaux syscall.SIGINT et syscall.SIGTERM et les relaie à un canal à l'aide de signal.Notify . Vous pouvez envoyer un crochet à ce goroutine en utilisant un canal et l'enregistrer dans une tranche de fonction. Lorsque le signal d'arrêt est détecté sur le canal, vous pouvez exécuter ces fonctions dans la tranche. Cela peut être utilisé pour nettoyer les ressources, attendre la fin des goroutines en cours d'exécution, conserver les données ou imprimer les totaux des exécutions partielles.
J'ai écrit un petit utilitaire simple pour ajouter et exécuter des hooks à l'arrêt. J'espère que cela peut être utile.
https://github.com/ankit-arora/go-utils/blob/master/go-shutdown-hook/shutdown-hook.go
Vous pouvez le faire de manière «différée».
exemple pour arrêter un serveur normalement:
la source
Il s'agit d'une autre version qui fonctionne au cas où vous auriez des tâches à nettoyer. Le code laissera le processus de nettoyage dans leur méthode.
si vous avez besoin de nettoyer la fonction principale, vous devez également capturer le signal dans le thread principal en utilisant go func ().
la source
Juste pour mémoire si quelqu'un a besoin d'un moyen de gérer les signaux sous Windows. J'avais besoin de gérer depuis prog A en appelant prog B via os / exec mais prog B n'a jamais pu se terminer gracieusement car l'envoi de signaux via ex. cmd.Process.Signal (syscall.SIGTERM) ou d'autres signaux ne sont pas pris en charge sous Windows. La façon dont j'ai géré est de créer un fichier temporaire comme un signal ex. .signal.term via prog A et prog B doit vérifier si ce fichier existe sur la base de l'intervalle, s'il existe, il quittera le programme et effectuera un nettoyage si nécessaire, je suis sûr qu'il existe d'autres moyens mais cela a fait l'affaire.
la source