¿En qué orden debo enviar señales para cerrar correctamente los procesos?
-
22-08-2019 - |
Pregunta
en un comentario en esta respuesta de otro pregunta, el comentarista dice:
¡No use Kill -9 a menos que sea absolutamente necesario!Sigkill no puede quedar atrapado para que el programa asesinado no pueda ejecutar ninguna rutina de cierre a EGborrar archivos temporales.Primero pruebe HUP (1), luego INT (2), luego QUIT (3)
Estoy de acuerdo en principio con SIGKILL
, pero el resto son novedades para mí.Dado que la señal predeterminada enviada por kill
es SIGTERM
, Yo esperaría que fuera la señal más comúnmente esperada para el cierre elegante de un proceso arbitrario.Además, he visto SIGHUP
Se usa por razones que no son de terminación, como decirle a un demonio "vuelva a leer su archivo de configuración". Y me parece que SIGINT
(la misma interrupción que normalmente obtendrías con Ctrl-C, ¿verdad?) no es tan ampliamente compatible como debería, o termina de manera bastante desagradable.
Dado que SIGKILL
es un último recurso - Qué señales y en qué orden, ¿debería enviar a un proceso arbitrario para cerrarlo de la manera más elegante posible?
Justifique sus respuestas con hechos que lo respalden (más allá de las preferencias u opiniones personales) o referencias, si puede.
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 ordenado de eliminación?
Solución
SIGTERM cuenta una aplicación termine. Las otras señales de decirle a la aplicación otras cosas que no están relacionados con el apagado, pero a veces pueden tener el mismo resultado. No utilice los. Si quieres una aplicación para apagar, dilo a. No se lo dé señales engañosas.
Algunas personas creen que la manera estándar inteligente de la terminación de un proceso es mediante el envío de una serie de señales, tales como HUP, INT, TERM y finalmente MATAR. Esto es ridículo. La señal adecuada para la terminación es SIGTERM y si SIGTERM no termina el proceso al instante, ya que es posible que prefiera, es porque la aplicación ha elegido para manejar la señal. Que significa que tiene una muy buena razón para no terminar inmediatamente: Tiene que ver el trabajo de limpieza. Si se interrumpe el trabajo de limpieza que con otras señales, no se sabe lo que los datos de la memoria aún no se ha guardado en el disco, lo que las aplicaciones cliente se dejan colgando o si usted está interrumpirlo "mitad de la frase" que es efectivamente la corrupción de datos.
Para obtener más información sobre lo que es el verdadero significado de las señales, ver sigaction (2). No se debe confundir "acción predeterminada" con "Descripción", que no son la misma cosa.
SIGINT se utiliza para señalar un interactivo "interrupción de teclado" del proceso. Algunos programas pueden manejar la situación de una manera especial con el propósito de usuarios de terminales.
SIGHUP se utiliza para indicar que el terminal ha desaparecido y ya no está mirando el proceso. Eso es todo. Algunos procesos optar por apagar en respuesta, por lo general debido a que su funcionamiento no tiene sentido sin un terminal, algunos optan por hacer otras cosas tales como archivos de configuración? Información.
SIGKILL se utiliza para eliminar la fuerza el proceso desde el núcleo. Es especial en el sentido de que no es en realidad una señal al proceso, sino que se interpreta por el núcleo directamente.
No envíe SIGKILL. SIGKILL debe ciertamente nunca se enviará por guiones. Si la aplicación se encarga de la SIGTERM, puede tomar un segundo para la limpieza, se puede tomar un minuto, puede tomar una hora . Dependiendo de lo que la aplicación tiene que hacer antes de que esté listo para terminar. Cualquier lógica que " asume " secuencia de limpieza de una aplicación ha tenido el tiempo suficiente y debe ser de acceso directo o SIGKILLed después de X segundos es simplemente mal .
La única razón por la que lo haría una aplicación necesidad a SIGKILL a finalizar, es si algo largó durante la secuencia de limpieza. En este caso, puede abrir un terminal y sigkill manualmente. Aparte de eso, la única otra razón por la que le sigkill algo es porque ¿Quieres para evitar que la limpieza a sí misma.
A pesar de que la mitad del mundo envía SIGKILL a ciegas después de 5 segundos que sigue siendo cosa muy mal hacer.
Otros consejos
Respuesta corta:Enviar SIGTERM
, 30 segundos después, SIGKILL
.Es decir enviar SIGTERM
, espera un poco (puede variar de un programa a otro, es posible que conozcas mejor tu sistema, pero con 5 a 30 segundos es suficiente.Al apagar una máquina, es posible que vea que espera automáticamente hasta 1'30 s.¿Por qué tanta prisa después de todo?), luego envía SIGKILL
.
Respuesta razonable: SIGTERM
, SIGINT
, SIGKILL
Esto es más que suficiente.El proceso muy Probablemente termine antes SIGKILL
.
Respuesta larga: SIGTERM
, SIGINT
, SIGQUIT
, SIGABRT
, SIGKILL
Esto es innecesario, pero al menos no estás engañando al proceso con respecto a tu mensaje.Todas estas señales hacer significa que desea que el proceso detenga lo que está haciendo y salga.
No importa qué respuesta elijas de esta explicación, ¡tenlo en cuenta!
Si envías una señal que significa otra cosa, el proceso puede manejarla de maneras 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, debes pensar en ti mismo como programador.¿Codificaría un controlador de funciones para, digamos, SIGHUP
¿Salir de un programa que se conecta con algo, o lo harías en bucle para intentar conectarte nuevamente?¡Ésa es la pregunta principal aquí!Por eso es importante enviar señales que signifiquen lo que usted pretende.
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 pedí en el orden que sugiero usar (por cierto, te sugiero que uses el respuesta razonable, no este de aquí), si realmente necesitas 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 así). completamente verdadero).
Las señales con un asterisco (*) son NO recomendado.Lo importante de estos es que es posible que nunca sepas para qué está programado.Especialmente SIGUSR
!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 improbable caso de que se solucione su finalización, el programa finalizará.
En la tabla, las señales con opciones predeterminadas para terminar y generar un volcado de núcleo se dejan al final, justo antes SIGKILL
.
Signal Value Action Comment
----------------------------------------------------------------------
SIGTERM 15 Term Termination signal
SIGINT 2 Term Famous CONTROL+C interrupt from keyboard
SIGHUP 1 Term Disconnected terminal or parent died
SIGPIPE 13 Term Broken pipe
SIGALRM(*) 14 Term Timer signal from alarm
SIGUSR2(*) 12 Term User-defined signal 2
SIGUSR1(*) 10 Term User-defined signal 1
SIGQUIT 3 Core CONTRL+\ or quit from keyboard
SIGABRT 6 Core Abort signal from abort(3)
SIGSEGV 11 Core Invalid memory reference
SIGILL 4 Core Illegal Instruction
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
Entonces sugeriría para esto respuesta larga 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 antes SIGUSR1
porque estamos mejor si el programa no maneja la señal.Y es mucho más probable que se maneje SIGUSR1
si maneja solo uno de ellos.
Por cierto, la MATANZA:no está mal enviar SIGKILL
a un proceso, como se indicó en otra respuesta.Bueno, piensa en lo que sucede cuando envías un shutdown
¿dominio?Lo intentará SIGTERM
y SIGKILL
solo.¿Por qué cree que es así?¿Y por qué necesitas otras señales, si el mismo shutdown
¿El comando usa solo estos dos?
Ahora, volvamos a la respuesta larga, este es un buen comentario:
for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done
Duerme durante 30 segundos entre señales.¿Por qué más necesitarías un un trazador de líneas? ;)
Además, recomendado:Pruébalo solo con señales. 15 2 9
desde el respuesta razonable.
seguridad:quitar el segundo echo
cuando esté listo para partir.lo llamo mi dry-run
para usuarios en línea.Úselo siempre para probar.
Guión mata con gracia
En realidad, estaba tan intrigado por esta pregunta que decidí crear un pequeño guión para hacer precisamente eso.Por favor, siéntete libre de descargarlo (clonarlo) aquí:
Enlace de GitHub a Repositorio Killgracefully
Normalmente debes enviar SIGTERM
, el valor predeterminado de la matanza. Es la opción predeterminada por una razón. Sólo si un programa no hace parada en una cantidad de tiempo razonable en caso de que recurrir a SIGKILL
. Pero en cuenta que con SIGKILL
el programa no tiene posibilidad de limpiar las cosas und datos podrían corromperse.
En cuanto a SIGHUP
, HUP
significa "colgar" e históricamente significó que el módem desconecta. Es esencialmente equivalente a SIGTERM
. La razón de que los demonios utilizan a veces SIGHUP
para reiniciar o volver a cargar config es que los demonios se desprenden de las terminales de control como un demonio no necesita los y por lo tanto nunca recibirá SIGHUP
, por lo que se consideró que la señal como "liberado" para uso general. No todos los demonios usan esto para recarga! La acción predeterminada para SIGHUP es terminar y muchos demonios se comporta de esa manera! Por lo que no puede ir a ciegas enviar SIGHUP
s a los demonios y esperando que les permite sobrevivir.
Editar SIGINT
es probablemente inadecuado para terminar un proceso, ya que está normalmente ligada a ^C
o lo que sea la configuración del terminal es interrumpir un programa. Muchos programas de captura de esto para sus propios fines, por lo que es bastante común para que no funcione. SIGQUIT
normalmente tiene el defecto de crear un volcado de memoria, y a menos que desee archivos principales por ahí que no es un buen candidato, ya sea.
Resumen:. Si envía SIGTERM
y el programa no muere dentro de su marco de tiempo después enviarlo SIGKILL
SIGTERM
en realidad significa el envío de una solicitud de un mensaje: " ¿sería tan amable y suicidarse ". Puede ser atrapado y manejado por aplicación para ejecutar el código de limpieza y apagado.
SIGKILL
no puede ser atrapado por la aplicación. Aplicación muere por el sistema operativo sin ninguna posibilidad para la limpieza.
Es típico para enviar SIGTERM
primero, dormir algún tiempo, a continuación, enviar SIGKILL
.
- SIGTERM es equivalente a "hacer clic en la 'X'" en una ventana.
- SIGTERM es lo que Linux utiliza en primer lugar, cuando se está cerrando.
Con toda la discusión pasando aquí, ningún código ha sido ofrecido. Esta es 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
HUP suena como basura para mí. Me lo envío para obtener un demonio para volver a leer su configuración.
SIGTERM puede ser interceptada; sus demonios sólo podría tener código de limpieza para funcionar cuando recibe esa señal. No se puede hacer eso por SIGKILL. Así, con SIGKILL usted no está dando el autor del demonio de las opciones.
Más sobre esto en Wikipedia