En un comentario sobre esta respuesta de otra pregunta , el comentarista dice:
¡No uses kill -9 a menos que sea absolutamente necesario! SIGKILL no se puede atrapar, por lo que el programa eliminado no puede ejecutar ninguna rutina de apagado para, por ejemplo, borrar archivos temporales. Primero intente HUP (1), luego INT (2), luego SALIR (3)
En principio estoy de acuerdo SIGKILL
, pero el resto son novedades para mí. Dado que la señal predeterminada enviada por kill
es SIGTERM
, esperaría que sea la señal más comúnmente esperada para un cierre ordenado de un proceso arbitrario. Además, lo he visto SIGHUP
utilizado por razones no terminantes, como decirle a un demonio "vuelva a leer su archivo de configuración". Y me parece que SIGINT
(la misma interrupción que obtendría normalmente con Ctrl-C, ¿verdad?) No es tan ampliamente compatible como debería ser, o termina de manera bastante desagradable.
Dado que SIGKILL
es un último recurso, ¿qué señales y en qué orden debe enviar a un proceso arbitrario para cerrarlo de la manera más elegante posible?
Si puede, sustente sus respuestas con hechos de apoyo (más allá de las preferencias u opiniones personales) o referencias.
Nota: Estoy particularmente interesado en las mejores prácticas que incluyen la consideración de bash / Cygwin.
Editar: Hasta ahora, nadie parece mencionar INT o QUIT, y hay una mención limitada de HUP. ¿Hay alguna razón para incluirlos en un proceso de matanza ordenado?
fuente
Respuestas:
SIGTERM le dice a una aplicación que finalice. Las otras señales le dicen a la aplicación otras cosas que no están relacionadas con el apagado, pero que a veces pueden tener el mismo resultado. No los uses. Si desea que una aplicación se cierre, dígale que lo haga. No le dé señales engañosas.
Algunas personas creen que la forma estándar inteligente de terminar un proceso es enviándole una gran cantidad de señales, como HUP, INT, TERM y finalmente KILL. Esto es ridículo. La señal correcta para la terminación es SIGTERM y si SIGTERM no termina el proceso instantáneamente, como podría preferir, es porque la aplicación ha elegido manejar la señal. Lo que significa que tiene una muy buena razón para no terminar de inmediato: tiene trabajo de limpieza por hacer. Si interrumpe ese trabajo de limpieza con otras señales, no se sabe qué datos de la memoria aún no se han guardado en el disco, qué aplicaciones cliente quedan colgadas o si lo está interrumpiendo "a mitad de frase", lo que efectivamente es corrupción de datos.
Para obtener más información sobre cuál es el significado real de las señales, consulte sigaction (2). No confunda "Acción predeterminada" con "Descripción", no son lo mismo.
SIGINT se utiliza para señalar una "interrupción de teclado" interactiva del proceso. Algunos programas pueden manejar la situación de una manera especial para los usuarios de terminales.
SIGHUP se utiliza para señalar que la terminal ha desaparecido y ya no está mirando el proceso. Eso es todo. Algunos procesos optan por cerrarse en respuesta, generalmente porque su funcionamiento no tiene sentido sin una terminal, algunos optan por hacer otras cosas, como volver a verificar los archivos de configuración.
SIGKILL se usa para eliminar forzosamente el proceso del kernel. Es especial en el sentido de que en realidad no es una señal para el proceso, sino que el kernel lo interpreta directamente.
No envíe SIGKILL. Ciertamente, SIGKILL nunca debería enviarse mediante scripts. Si la aplicación maneja el SIGTERM, la limpieza puede demorar un segundo, puede demorar un minuto, puede demorar una hora . Dependiendo de lo que tenga que hacer la aplicación antes de que esté lista para finalizar. Cualquier lógica que " asume " que la secuencia de limpieza de una aplicación ha tardado lo suficiente y necesita ser atajo o SIGKILL después de X segundos es simplemente errónea .
La única razón por la que una aplicación necesitaría un SIGKILL para terminar es si algo salió mal durante su secuencia de limpieza. En cuyo caso puede abrir una terminal y SIGKILL manualmente. Aparte de eso, la única otra razón por la que SIGKILL algo es porque QUIERES evitar que se limpie solo.
A pesar de que la mitad del mundo envía SIGKILL a ciegas después de 5 segundos, sigue siendo algo terriblemente incorrecto.
fuente
Respuesta corta : Enviar
SIGTERM
, 30 segundos más tarde,SIGKILL
. Es decir, envíeSIGTERM
, espere un poco (puede variar de un programa a otro, es posible que conozca mejor su sistema, pero de 5 a 30 segundos es suficiente. Al apagar una máquina, es posible que la vea automáticamente esperando hasta 1'30 s). ¿Por qué la prisa, después de todo?), Luego envíaSIGKILL
.Respuesta razonable :
SIGTERM
,SIGINT
,SIGKILL
Esto es más que suficiente. Es muy probable que el proceso termine antesSIGKILL
.Respuesta larga :
SIGTERM
,SIGINT
,SIGQUIT
,SIGABRT
,SIGKILL
Esto es innecesario, pero al menos no está engañando el proceso con respecto a su mensaje. Todas estas señales no significan desea que el proceso para detener lo que está haciendo y salir.
No importa qué respuesta elija de esta explicación, ¡téngalo en cuenta!
Si envía una señal que significa otra cosa, el proceso puede manejarla de formas muy diferentes (por un lado). Por otro lado, si el proceso no maneja la señal, no importa lo que envíe después de todo, el proceso se cerrará de todos modos (cuando la acción predeterminada es terminar, por supuesto).
Por lo tanto, debe pensar como programador. ¿Codificaría un controlador de funciones para, digamos,
SIGHUP
salir de un programa que se conecta con algo, o lo haría un bucle para intentar conectarse de nuevo? ¡Esa es la pregunta principal aquí! Por eso es importante enviar señales que signifiquen lo que pretendes.Respuesta larga casi estúpida :
La siguiente tabla contiene las señales relevantes y las acciones predeterminadas en caso de que el programa no las maneje.
Los ordené en el orden que sugiero usar (por cierto, le sugiero que use la respuesta razonable , no esta aquí), si realmente necesita probarlos todos (sería divertido decir que la tabla está ordenada en términos de la destrucción que pueden causar, pero eso no es del todo cierto).
NO se recomiendan las señales con un asterisco (*) . Lo importante de estos es que es posible que nunca sepa para qué está programado.
SIGUSR
¡ Especialmente ! Puede iniciar el apocalipsis (¡es una señal gratuita para que un programador haga lo que quiera!). Pero, si no se maneja O, en el caso poco probable, se maneja para terminar, el programa terminará.En la tabla, las señales con opciones predeterminadas para terminar y generar un volcado de memoria se dejan al final, justo antes
SIGKILL
.Entonces sugeriría para esta larga respuesta casi estúpida :
SIGTERM
,SIGINT
,SIGHUP
,SIGPIPE
,SIGQUIT
,SIGABRT
,SIGKILL
Y finalmente, el
Definitivamente estúpida respuesta larga y larga :
No intentes esto en casa.
SIGTERM
,SIGINT
,SIGHUP
,SIGPIPE
,SIGALRM
,SIGUSR2
,SIGUSR1
,SIGQUIT
,SIGABRT
,SIGSEGV
,SIGILL
,SIGFPE
Y si nada funcionó,SIGKILL
.SIGUSR2
debe probarse antesSIGUSR1
porque estamos mejor si el programa no maneja la señal. Y es mucho más probable que manejeSIGUSR1
si solo maneja uno de ellos.Por cierto, el KILL : no está mal enviar
SIGKILL
a un proceso, como se indicó en otra respuesta. Bueno, piensa en lo que pasa cuando envías unshutdown
comando. Lo intentaráSIGTERM
ySIGKILL
solo. ¿Por qué cree que es así? ¿Y por qué necesita otras señales, si el mismoshutdown
comando usa solo estas dos?Ahora, volviendo a la respuesta larga , este es un buen delineador:
for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done
Duerme 30 segundos entre señales. ¿Por qué más necesitarías un delineador ? ;)
Además, se recomienda: inténtelo solo con señales
15 2 9
de la respuesta razonable .seguridad : retire el segundo
echo
cuando esté listo para comenzar. Yo lo llamo midry-run
para los online . Úselo siempre para probar.Guión killgracefully
En realidad, estaba tan intrigado por esta pregunta que decidí crear un pequeño guión para hacer precisamente eso. Por favor, siéntase libre de descargarlo (clonarlo) aquí:
Enlace de GitHub al repositorio de Killgracefully
fuente
Normalmente enviarías
SIGTERM
, el valor predeterminado de kill. Es el predeterminado por una razón. Solo debe recurrir a él si un programa no se apaga en un período de tiempo razonableSIGKILL
. Pero tenga en cuenta que conSIGKILL
el programa no hay posibilidad de limpiar las cosas y los datos podrían corromperse.En cuanto a
SIGHUP
,HUP
significa "colgar" e históricamente significaba que el módem se desconectaba. Es esencialmente equivalente aSIGTERM
. La razón por la que los demonios a veces usanSIGHUP
para reiniciar o recargar la configuración es que los demonios se separan de cualquier terminal de control ya que un demonio no los necesita y, por lo tanto, nunca los recibiríaSIGHUP
, por lo que la señal se consideró como "liberada" para uso general. ¡No todos los demonios usan esto para recargar! ¡La acción predeterminada para SIGHUP es terminar y muchos demonios se comportan de esa manera! Por lo tanto, no puede enviar mensajesSIGHUP
de correo electrónico a los demonios y esperar que sobrevivan.Editar:
SIGINT
probablemente sea inapropiado terminar un proceso, ya que normalmente está vinculado a^C
o cualquiera que sea la configuración del terminal para interrumpir un programa. Muchos programas capturan esto para sus propios fines, por lo que es lo suficientemente común como para que no funcione.SIGQUIT
normalmente tiene el valor predeterminado de crear un volcado del núcleo y, a menos que desee archivos del núcleo por ahí, tampoco es un buen candidato.Resumen: si envía
SIGTERM
y el programa no muere dentro de su plazo, envíeloSIGKILL
.fuente
SIGTERM
en realidad significa enviar un mensaje a una aplicación: " ¿Sería tan amable de suicidarse? ". Puede ser atrapado y manejado por la aplicación para ejecutar el código de limpieza y apagado.SIGKILL
no puede ser atrapado por aplicación. La aplicación es eliminada por el sistema operativo sin ninguna posibilidad de limpieza.Es típico enviar
SIGTERM
primero, dormir un rato y luego enviarSIGKILL
.fuente
fuente
Con toda la discusión en curso aquí, no se ha ofrecido ningún código. Aquí está mi opinión:
#!/bin/bash $pid = 1234 echo "Killing process $pid..." kill $pid waitAttempts=30 for i in $(seq 1 $waitAttempts) do echo "Checking if process is alive (attempt #$i / $waitAttempts)..." sleep 1 if ps -p $pid > /dev/null then echo "Process $pid is still running" else echo "Process $pid has shut down successfully" break fi done if ps -p $pid > /dev/null then echo "Could not shut down process $pid gracefully - killing it forcibly..." kill -SIGKILL $pid fi
fuente
HUP me suena a basura. Lo enviaría para que un demonio volviera a leer su configuración.
SIGTERM puede interceptarse; sus demonios pueden tener código de limpieza para ejecutar cuando reciba esa señal. No puede hacer eso por SIGKILL. Por lo tanto, con SIGKILL no le está dando ninguna opción al autor del demonio.
Más sobre eso en Wikipedia
fuente