Quiero capturar la señal Ctrl+C( SIGINT
) enviada desde la consola e imprimir algunos totales de ejecución parcial.
¿Es esto posible en Golang?
Nota: Cuando publiqué la pregunta por primera vez, estaba confundido acerca de Ctrl+Cser en SIGTERM
lugar de SIGINT
.
for sig := range g {
, también puede usar<-sigchan
como en esta respuesta anterior: stackoverflow.com/questions/8403862/…go run
de una consola y envía un SIGTERM a través de ^ C, la señal se escribe en el canal y el programa responde, pero parece caer inesperadamente del bucle. ¡Esto se debe a que SIGRERMgo run
también funciona! (¡Esto me ha causado una confusión sustancial!)runtime.Gosched
en un lugar apropiado (en el bucle principal de su programa, si tiene una)Esto funciona:
fuente
Para agregar un poco a las otras respuestas, si realmente desea atrapar SIGTERM (la señal predeterminada enviada por el comando kill), puede usar
syscall.SIGTERM
en lugar de os.Interrupt. Tenga en cuenta que la interfaz syscall es específica del sistema y podría no funcionar en todas partes (por ejemplo, en Windows). Pero funciona muy bien para atrapar ambos:fuente
signal.Notify
función permite especificar varias señales a la vez. Por lo tanto, puede simplificar su código asignal.Notify(c, os.Interrupt, syscall.SIGTERM)
.os.Kill
corresponde asyscall.Kill
, que es una señal que puede enviarse pero no capturarse. Es equivalente al comandokill -9 <pid>
. Si desea atraparkill <pid>
y apagar con gracia, debe usarsyscall.SIGTERM
.Había (al momento de publicar) uno o dos pequeños errores tipográficos en la respuesta aceptada arriba, así que aquí está la versión limpia. En este ejemplo, detengo el generador de perfiles de CPU cuando recibo Ctrl+ C.
fuente
runtime.Gosched
en un lugar apropiado (en el bucle principal de su programa, si tiene una)Todo lo anterior parece funcionar cuando se empalma, pero la página de señales de gobyexample tiene un ejemplo realmente limpio y completo de captura de señal. Vale la pena agregar a esta lista.
fuente
La muerte es una biblioteca simple que utiliza canales y un grupo de espera para esperar las señales de apagado. Una vez que se haya recibido la señal, llamará a un método de cierre en todas sus estructuras que desea limpiar.
fuente
Puede tener una rutina diferente que detecte las señales syscall.SIGINT y syscall.SIGTERM y las transmita a un canal utilizando la señal . Puede enviar un gancho a esa rutina utilizando un canal y guardarlo en un segmento de función. Cuando se detecta la señal de apagado en el canal, puede ejecutar esas funciones en el segmento. Esto se puede usar para limpiar los recursos, esperar a que finalicen las rutinas de ejecución, conservar datos o imprimir totales de ejecución parciales.
Escribí una utilidad pequeña y simple para agregar y ejecutar ganchos en el apagado. Espero que pueda ser de ayuda.
https://github.com/ankit-arora/go-utils/blob/master/go-shutdown-hook/shutdown-hook.go
Puede hacer esto de manera 'diferida'.
ejemplo para apagar un servidor con gracia:
fuente
Esta es otra versión que funciona en caso de que tenga que limpiar algunas tareas. El código dejará el proceso de limpieza en su método.
en caso de que necesite limpiar la función principal, también necesita capturar la señal en el hilo principal usando go func ().
fuente
Solo para el registro si alguien necesita una forma de manejar las señales en Windows. Tenía un requisito para manejar desde el programa A llamando al programa B a través de os / exec pero el programa B nunca pudo terminar con gracia porque enviaba señales a través de ex. cmd.Process.Signal (syscall.SIGTERM) u otras señales no son compatibles con Windows. La forma en que manejé es creando un archivo temporal como una señal ex. .signal.term a través del programa A y el programa B deben verificar si ese archivo existe en la base de intervalos, si existe el archivo, saldrá del programa y se encargará de una limpieza si es necesario, estoy seguro de que hay otras formas, pero esto hizo el trabajo.
fuente