Las interrupciones de software en los sistemas Linux y Unix se realizan a través de señales. Hay muchas señales de Linux diferentes, pero algunas se resaltan y es esencial comprenderlas y conocerlas: SIGINT, SIGTERM y SIGKILL. Así es como funcionan.
Que es un Señal de Linux?
Todos entendemos que una luz roja significa que tenemos que dejar de caminar o conducir. De manera equivalente, en los sistemas Linux y Unix, se puede pasar una señal a un programa o servicio en ejecución para que interactúe con él. A modo de ejemplo, uno podría enviar una señal de semáforo en rojo a un programa simplemente emitiendo un SIGTERM
señal.
Del mismo modo que con un semáforo en rojo, las personas pueden decantarse por seguir caminando o conduciendo cuando el semáforo está en rojo. Aunque puede que no sea una idea segura para todos los involucrados, una SIGTERM
el envío de señal a un procedimiento hará exactamente eso; el procedimiento / programa puede elegir por ignorar dicha señal.
Todas las señales básicas de Linux disponen un número (1-30 +). Después de un tiempo, un usuario competente de Linux de forma general conocerá uno o más de estos. A modo de ejemplo, el SIGTERM
la señal coincide con el número 15 y la señal 9 (SIGKILL
) es probablemente el más conocido, dado que posibilita terminar forzosamente un procedimiento, a diferencia de nuestro SIGTERM
ejemplo de luz roja.
Aquí vemos la pantalla principal de htop
(puede instalar esta práctica utilidad escribiendo sudo apt install htop
en Ubuntu / Mint, o sudo yum install htop
en RedHat / Centos / Fedora) con una serie de señales de terminación y otras (más abajo en el listado; hay 37 en total) que se pueden enviar a un procedimiento previamente seleccionado a la derecha. Uno puede elegir un procedimiento presionando el cursor arriba / abajo y después enviar una señal usando F9.
SIGKILL & SIGTERM
Aunque el nombre puede sonar un poco siniestro, la jerga común de Linux para la terminación de procesos es que uno «mata» un procedimiento. En términos generales, solo querremos terminar un procedimiento con un -9
(SIGKILL
) señal si dicho procedimiento / programa está bloqueado. Tenga en cuenta que siempre que hablamos de procedimiento o programa, las palabras se pueden intercambiar a voluntad. Simplemente, un procedimiento es cualquier programa (o servicio) en ejecución al que se le ha dado un PID (un identificador de procedimiento).
Veamos un ejemplo de cómo finalizar un procedimiento en segundo plano en ejecución a través de un SIGKILL
señal al procedimiento en ejecución. Tenga en cuenta que, como se explicó SIGKILL
es bastante destructivo y terminará el procedimiento sin importar lo que el procedimiento quiera hacer con la señal. El procedimiento puede capturar y redirigir varias señales, mientras que otras no.
Aquí empezamos un sleep 1800
en segundo plano (usando &
al final del comando), que se inició como el primero ([1]
) procedimiento en segundo plano con PID 574660
. Posteriormente, matamos ese procedimiento en segundo plano usando kill -9 574660
, donde el -9
representa SIGKILL
.
Aunque el procedimiento finaliza inmediatamente, no vemos el mensaje de finalización (procedimiento en segundo plano 1
asesinado, dicho de otra forma, [1]+ Killed
) cuando el símbolo del sistema regresa antes de que se muestre el mensaje, dicho de otra forma, devolver la línea de comando fue una operación más rápida que la finalización del procedimiento o equivalente.
Verificamos la lista de procesos haciendo grepping para el PID ps -ef | grep 574660
. Aunque puede haber algo de salida, la salida que se muestra es solo para nuestra ejecución grep
mando; los sleep
El procedimiento ya ha terminado.
Evaluemos lo mismo con SIGTERM
, dicho de otra forma kill -15 ${PID}
dónde ${PID}
es el procedimiento que queremos terminar.
Tuvimos que presionar enter para activar / mostrar el mensaje de terminación (como se explicó previamente). Podemos ver que el programa terminó correctamente de nuevo. A pesar de esto, esta vez, aún cuando invisible para este ejemplo en particular (¡sigue leyendo!), Internamente dentro del sleep
código del programa, las cosas fueron un poco diferentes.
Para este caso (usando -15
dicho de otra forma SIGTERM
para terminar el procedimiento), el sleep
El procedimiento fue notificado y tuvo la posibilidad de manejar internamente la señal. Posteriormente, podría responder autoterminando, ignorando la señal o a través de cualquier otra acción desarrollada en el código. Además podemos probar que esto es cierto comprobando la señal de salida y / o la salida:
Aqui empezamos el procedimiento sleep 2000
dos veces, y después usó otra sesión de shell / terminal para terminar el programa. La primera vez que usamos kill -9
y la segunda vez que usamos kill -15
para detener el sleep
procedimiento.
Inmediatamente notamos cómo regresa la salida. Killed
en el primero (kill -9
acción) instancia. Para el segundo intento (usando kill -15
), vemos la salida Terminated
en lugar de; el programa finalizó automáticamente. Posteriormente a las respectivas terminaciones, además verificamos las señales de salida y descubrimos que los códigos de salida eran diferentes.
¿Debido a que es esto importante? Considere programas más grandes; en esta circunstancia, solo estábamos terminando un simple sleep
mando. No se manejaban datos, no se enviaba tráfico de un lado a otro, etc. Pero, ¿qué pasaría si enviamos un kill -9
comando a nuestro servidor de base de datos (esto, en general, requeriría privilegios de nivel de raíz / sudo)?
Activaría la base de datos para entrar en modo de recuperación de fallos la próxima vez que se inicie debido a que, hasta donde sabe el software de la base de datos, todo lo que sucedió fue «estaba allí» seguido de «nada». Dicho de otra forma, se estrelló. Si en cambio hubiéramos emitido un kill -15
, el software de la base de datos podría haber realizado un apagado controlado, a modo de ejemplo, primero bloqueando la conexión de nuevos usuarios, después desconectando / terminando a los usuarios existentes, después terminando de escribir datos, etc. antes de en resumen auto-terminar.
Envío de señales de Linux con secuencias de teclado
¿Sabías que cada vez que enviaste un CTRL+c
secuencia de teclas a un programa en ejecución, a modo de ejemplo en un terminal, que en su lugar un SIGINT
¿se ha enviado? Retrocedamos a nuestra confianza sleep
comando y prueba esto:
Aquí empezamos sleep
de nuevo, y después presionó la combinación de teclado CTRL+c
. El programa terminó, o mejor fue interrumpido por el SIGINT
señal que se envió. Solicitamos el código de salida y confirmamos que una vez más el código de salida es distinto a las señales anteriores.
Tenga en cuenta que este código de salida, para dormir, siempre coincidirá con la señal enviada, aún cuando es factible que no se cubran todas las señales. Dicho de otra forma, al utilizar CTRL+c
en la línea de comando, el código de salida siempre será 130
, 137
cuando asesinado con kill -9
, y 143
cuando kill -15
se utilizó.
Puede probar los códigos de salida de los comandos consultando el $?
variable, que contiene el código de salida del comando anterior (siempre que no haya comenzado un nuevo comando). Conocer el código de salida de un comando dado en una situación particular, y / o como consecuencia de una señal particular enviada a ese comando, ayuda cuando se crean scripts para soluciones que manejan otros procesos, etc. (que es el caso de muchos scripts de shell, especialmente al administrar servidores o entornos automatizados).
Otra secuencia de teclado de uso frecuente es CTRL+z
. Esto enviará un SIGTSTP
señal, una suspend
señal que coloca inmediatamente un procedimiento en suspensión hasta (a modo de ejemplo) un 'fg'
El comando se emite para el mismo procedimiento que lo traerá de vuelta al primer plano.
Para obtener más información sobre la administración de procesos, consulte Bash Process Termination Hacks.
Terminando
En este post, analizamos las señales de Linux más importantes y cómo podemos usarlas prácticamente en un entorno Linux o Unix. Conocer las señales básicas de Linux le ayuda a uno con el uso y la administración diarios de Linux, a modo de ejemplo, cuando un procedimiento se cuelga y debe terminarse con kill -9
. En un post futuro, podemos considerar la captura de una señal usando el trap
comando desde el interior de un script Bash, lo que posibilita establecer un procedimiento personalizado que se ejecutará cuando se emita dicha señal.
Si disfrutó leyendo este post, eche un vistazo a nuestra serie de automatización Bash que comienza en Bash Automation & Scripting Basics. En el tercer post de esa serie, además analizamos la administración de procesos en segundo plano, que se mencionó previamente en este post.