¿Por qué Ctrl-C no mata la Terminal en sí?


Respuestas:


48

Ctrl+ Ces la señal de interrupción. Cuando escribe esto en una terminal, bash envía SIGINT al trabajo en primer plano. Si no hay trabajo (que es el caso cuando acaba de abrir un terminal), no pasa nada. El programa emulador de terminal no es un trabajo que se ejecuta en el shell, por lo tanto, no recibe la señal y no se cierra.

Si desea cerrar el terminal con una tecla de control, use Ctrl+ D(EOF) que hace que bash salga (y también cierra el terminal).

Ver también: Bash Guía para principiantes sobre señales y más profundidad Cómo funciona el manejo de señales
nota: esta respuesta se ha editado desde que se publicaron los comentarios


44
El término apropiado es que el shell "atrapará" la señal. Una historia diferente es cuando lanzas una ventana de terminal desde otra ventana. Enviar ctrl + c a la ventana principal matará el proceso secundario.
Sergiy Kolodyazhnyy

1
Además, las ventanas GUI también pueden recibir instrucciones para atrapar señales específicas provenientes del servidor X11. Así es como puede tener ventanas emergentes que le notifiquen sobre el trabajo no guardado, o abrir pestañas como en los navegadores
Sergiy Kolodyazhnyy

8
@chrylis el programa de terminal solo envía el carácter ctrl-c, en realidad es la capa de kernel tty que lo convierte en la señal.
Random832

3
@chrylis: Y el terminal, o un programa que se ejecuta dentro de él, por ejemplo, un editor de texto, bien puede traducir Ctl-C a alguna otra acción.
jamesqf

3
No creo bashque termine ningún programa cuando se presione ctrl-c. Simplemente le dirá al núcleo qué grupo de proceso está activo y el núcleo generará una señal a ese grupo de proceso cuando reciba ctrl-c del programa terminal.
Kasperd

32

La ^Cpulsación de teclas, como otras pulsaciones de teclas *, no es mágica: envía un código de tecla a cualquier programa que tenga el foco. (En X, el código clave es 54 para el Ccon un modificador de 0x4 para Ctrl.) El programa que recibe la secuencia de teclas es responsable de hacer algo apropiado con ellas: recuerde que en muchas aplicaciones GUI, la pulsación de teclas se copia en el portapapeles.

Cuando un emulador de terminal GUI (por ejemplo, Konsole) o un terminal virtual recibe una pulsación de tecla que interpreta ^C, puede hacer una de tres cosas. Si el terminal está en modo sin procesar , entonces el programa en ejecución le ha pedido al terminal que no realice ningún manejo de teclas especiales y que las pase directamente al programa. Algunos programas que admiten funciones avanzadas como la edición de líneas reciben entradas de teclado en alguna configuración entre pulsaciones de teclas sin procesar completas y líneas de texto procesadas; bash, por ejemplo, recibe pulsaciones de teclas de una en una. ^Cel terminal lo interpreta, pero la clave de retroceso se envía al shell tal como está.

Sin embargo, la mayoría de los programas usan el modo cocinado (porque no es sin formato), donde el terminal interpreta algunas teclas básicas antes de enviarlas al programa (es por eso que puede usar la tecla de retroceso cat). En este modo, el terminal mismo traduce la ^Cpulsación de tecla en una SIGINTseñal y la envía al proceso secundario. Como el terminal generó la señal, no se confundirá ni terminará.

  • SysRq Realmente es magia.

Obviamente no es súper relevante aquí, pero para la computación general hay más pulsaciones de teclas mágicas por ahí. Lo más famoso, Ctrl+ Alt+ Deleteen el mundo de Windows, donde la combinación de teclas está bastante cerca de la magia (se puede usar para hacer que Windows funcione, ¡eso es bastante mágico en sí mismo!), Ya que está codificado en el sistema para interrumpir y anular casi todo, bastante similar a SysRqen ese sentido.
KRyan

77
Bash no usa el modo sin formato: usa el modo de carácter a la vez, es decir , cbreak/ -icanonpero deja el isigmodo establecido y recibe señales reales cuando presiona las teclas que están asignadas a ellos. Se maneja SIGINTcomportándose como lo describió (no solo cancela la edición de línea, sino que también cancela cualquier comando interno que pueda estar ejecutándose en un bucle), e ignora por completo SIGTSTPy SIGQUIT. Otros programas, como vi, pueden no serlo.
Random832

1
@KRyan Ctrl+ Alt+ Deletesolía ser aún más mágico de lo que es hoy: blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 . Aunque soy una persona de Linux en el fondo, a menudo me impresiona mucho la medida en que Windows hizo las cosas fáciles de usar y lógicas con recursos tan limitados en los primeros días.
Muzer

En algunos sistemas operativos, incluso si otro programa se ha enfocado, el sistema (¿supongo que el administrador de ventanas?) Realmente presiona las teclas antes de que lo haga el emulador de terminal. Si puede configurar métodos abreviados de teclado para abrir ventanas, abrir aplicaciones, activar secuencias de comandos y luego, antes de enviar las teclas presionadas al emulador de terminal, se verifican los métodos abreviados que haya configurado. Y otro ejemplo si no tiene aplicaciones abiertas ^cno matará al administrador de ventanas :). No puedo comentar sobre el carácter crudo / cocinado a la vez, pero la respuesta es acertada sobre cómo se está generando esa pulsación de teclaSIGINT
Ajay

2
" modo cocinado (porque no está crudo)": estoy ... sin palabras. Después de todos estos años, nunca hice la conexión.
isanae

8

^Cgeneralmente se asigna (ver stty -a) a la SIGINTseñal (ver man 7 signal).

Un no capturado SIGINTinterrumpe el proceso de ejecución, PERO ...

SIGINT es una de las señales para las que un proceso puede especificar el comportamiento ("Capturar una señal").

Lo que llama "la terminal" se atrapa SIGINTy vuelve a funcionar.


7

Cuando era un principiante, me faltaba la parte de que cuando estaba usando la línea de comando en realidad estaba usando dos programas separados, un terminal y un shell (por ejemplo, bash)

El shell es lo que probablemente ya conoces, un programa que toma como comandos de entrada o scripts, los ejecuta e imprime su salida.

El terminal en el otro lado es como un hombre en el medio entre el usuario y un programa (cuyo programa suele ser un shell como bash o fish). Lo que hace el terminal es leer la entrada, por ejemplo, desde el teclado, tal vez procesar esa entrada de alguna manera y redirigirla al otro programa (bash).

También esto funciona de la otra manera, cuando el otro programa emite algo, ese algo se redirige al terminal, entonces es el trabajo del terminal enviar ese algo a la pantalla. Entre obtener la entrada e imprimirla en la pantalla, el terminal puede interpretar la entrada que recibe de varias maneras.

Por ejemplo, si un programa genera la siguiente secuencia:

\e[0;31m some extra foobar text

El terminal mostrará en la pantalla "texto extra de foobar" con letras de color rojo. Esto se debe a que el terminal elige tratar ese código extraño de una manera especial, código que le indica que imprima la siguiente salida en rojo.

De manera similar, cuando el usuario presiona Ctrl - C, lo único especial sobre esto es que el terminal elige tratarlo de una manera especial, no hay nada especial sobre esta secuencia de teclas. Específicamente, esto sugiere que envió la señal de interrupción (SIGINT) al proceso que se ejecuta dentro del terminal, que es el shell. Si en ese momento existe algún programa que ha sido generado por el shell y actualmente se está ejecutando en primer plano, también recibe la señal. Ahora el shell tiene un controlador especial para esta señal y no pasa nada. Pero la mayoría de los programas tienen los controladores predeterminados que en el caso de SIGINT simplemente salen.


5

Cada señal tiene una acción predeterminada asociada a ella. La acción predeterminada para una señal es la acción que realiza un script o programa cuando recibe una señal.

Ctrl+ Cenvía la señal de "interrupción" ( SIGINT ), que por defecto termina el proceso al trabajo que se ejecuta en primer plano.

Ctrl+ Dle dice al terminal que debe registrar un EOF en la entrada estándar, que bash interpreta como un deseo de salir .

Un proceso puede elegir ignorar la señal INT, y Bash lo hace cuando se ejecuta en modo interactivo.

Del manual :

Cuando bash es interactivo, en ausencia de trampas, ignora SIGTERM (para que kill 0 no mate a un shell interactivo), y SIGINT es capturado y manejado (de modo que la espera incorporada es interrumpible). En todos los casos, bash ignora SIGQUIT. Si el control de trabajo está vigente, bash ignora SIGTTIN, SIGTTOU y SIGTSTP.


Entiéndelo con trampa :

trap es una función integrada en el shell que responde a señales de hardware y otros eventos. Define y activa los controladores que se ejecutarán cuando el shell reciba señales u otras condiciones especiales.

trap [-lp] [arg] [sigspec …]

-l imprima una lista de nombres de señales y sus números correspondientes.
-pmuestra los comandos de trampa asociados con cada SIGNAL_SPEC.

Los argumentos deben leerse y ejecutarse cuando el shell recibe la señal sigspec. Cada sigspec es un nombre de señal o un número de señal. Los nombres de las señales no distinguen entre mayúsculas y minúsculas y el prefijo SIG es opcional.

Si un sigspec es 0 o EXIT , arg se ejecuta cuando el shell sale. Para entenderlo, cierre el terminal y ábralo después de editar la siguiente línea en el .bashrcarchivo.

trap 'notify-send "Ctrl D pressed"' 0

Ctrl D es similar al exitcomando para salir de la terminal.

Si desea que Bash salga al recibir la señal INT, incluso en modo interactivo, puede agregar lo siguiente a su ~/.bashrc:

trap 'exit' INT

o

trap 'exit' 2

1
Parece legítimo !!
luv.preet
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.