Je veux capturer le Ctrl+C ( SIGINT
) envoyé par la console et d'imprimer des totaux partiels d'exécution.
Je vois que vous appelez simplement Notify() au lieu de signal.Notify(). Est-ce que c'est la même chose ?
Je veux capturer le Ctrl+C ( SIGINT
) envoyé par la console et d'imprimer des totaux partiels d'exécution.
Vous pouvez utiliser le os/signal pour traiter les signaux entrants. Ctrl + C es SIGINT Vous pouvez donc l'utiliser pour piéger 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 en sorte que votre programme se termine et imprime des informations vous appartient entièrement.
Je vois que vous appelez simplement Notify() au lieu de signal.Notify(). Est-ce que c'est la même chose ?
@SebastiánGrignoli : Erreur de transcription. Taper directement du code dans SO ne conduit pas toujours à quelque chose qui peut effectivement être exécuté. Je vais corriger cela.
Ok. J'ai demandé parce que j'ai vu ce genre d'appel (en omettant le préfixe) partout dans la documentation des bibliothèques. Je pense qu'ils font référence à l'appel de la fonction depuis l'intérieur des bibliothèques...
Ça marche :
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
}
}
Passage en caisse dans la Terrain de jeux
Pour les autres lecteurs : Regardez la réponse de @adamonduty pour savoir pourquoi vous voulez attraper os.Interrupt et syscall.SIGTERM. Il aurait été bien d'inclure son explication dans cette réponse, surtout qu'il a posté des mois avant vous.
Pour compléter légèrement les 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 sous Windows). Mais elle fonctionne bien pour attraper les deux :
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
....
@Eclipse Grande question ! os.Kill
correspond à a syscall.Kill
qui est un signal qui peut être envoyé mais pas capté. C'est l'équivalent de la commande kill -9 <pid>
. Si vous voulez attraper kill <pid>
et s'éteindre de manière gracieuse, vous devez utiliser syscall.SIGTERM
.
Il y avait (au moment de la publication) une ou deux petites fautes de frappe dans la réponse acceptée ci-dessus, voici donc la version corrigée. Dans cet exemple, j'arrête le profileur de CPU lorsque je reçois le message suivant Ctrl + 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)
}
}()
Tout ce qui précède semble fonctionner lorsqu'il est épissé, mais Page des signaux de gobyexample a un exemple vraiment propre et complet de capture de signal. Il mérite d'être ajouté à cette liste.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
fmt.Println()
fmt.Println(sig)
done <- true
}()
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
}
Source : gobyexample.com/signals
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.