Por que Ctrl-C não mata o próprio terminal?


Respostas:


48

Ctrl+ Cé o sinal de interrupção. Quando você digita isso em um terminal, o bash envia o SIGINT para o trabalho em primeiro plano. Se não houver trabalho (como é o caso quando você acabou de abrir um terminal), nada acontece. O programa emulador de terminal não é um trabalho em execução no shell; portanto, ele não recebe o sinal e não fecha.

Se você deseja fechar o terminal com uma tecla de controle, use Ctrl+ D(EOF), que faz com que o bash saia (e fecha o terminal também).

Consulte também: Guia do Iniciante do Bash sobre sinais e com mais profundidade Como funciona o tratamento de sinais
nota: esta resposta foi editada desde que os comentários foram postados


4
O termo apropriado é que o shell "interceptará" o sinal. História diferente é quando você inicia uma janela de terminal de dentro de outra janela. Enviar ctrl + c para a janela pai matará o processo filho.
Sergiy Kolodyazhnyy

1
Além disso, as janelas da GUI também podem ser instruídas para capturar sinais específicos provenientes do servidor X11. É assim que você pode ter popups notificando-o do trabalho não salvo, ou abas abertas como em navegadores
Sergiy Kolodyazhnyy

8
@chrylis o programa do terminal apenas envia o caractere ctrl-c, na verdade é a camada tty do kernel que o transforma no sinal.
precisa saber é o seguinte

3
@chrylis: E o terminal, ou um programa em execução dentro dele - por exemplo, um editor de texto - pode muito bem converter o Ctl-C para alguma outra ação.
jamesqf

3
Eu não acho bashque terminará nenhum programa quando ctrl-c for pressionado. Ele apenas informará ao kernel qual grupo de processos está ativo e o kernel gerará um sinal para esse grupo de processos quando receber ctrl-c do programa do terminal.
kasperd

32

O ^Cpressionamento de tecla, como outros pressionamentos de tecla *, não é mágico - ele envia um código de tecla para o programa em foco. (No X, o código-chave é 54 para o Cmodificador de 0x4 para Ctrl.) O programa que está recebendo o fluxo de chaves é responsável por fazer algo apropriado com eles - lembre-se de que em muitos aplicativos da GUI, o pressionamento de tecla é copiado para a área de transferência.

Quando um emulador de terminal da GUI (por exemplo, Konsole) ou um terminal virtual recebe um pressionamento de tecla que ele interpreta como ^C, ele pode fazer uma de três coisas. Se o terminal estiver no modo bruto , o programa em execução solicitou que o terminal não execute nenhuma manipulação de chaves especiais e as passe diretamente para o programa. Alguns programas que oferecem suporte a recursos avançados, como edição de linha, recebem entrada do teclado em alguma configuração entre pressionamentos de tecla brutos completos e linhas de texto processadas; bash, por exemplo, recebe pressionamentos de tecla um de cada vez. ^Cé interpretado pelo terminal, mas a tecla backspace é enviada ao shell como está.

A maioria dos programas, no entanto, usa o modo preparado (porque não é cru), onde o terminal interpreta algumas teclas básicas antes de enviá-las ao programa (é por isso que você pode usar backspace cat). Nesse modo, o próprio terminal converte o ^Cpressionamento de tecla em um SIGINTsinal e o envia para o processo filho. Como o terminal gerou o sinal, ele não ficará confuso e será encerrado.

  • SysRq realmente é mágico.

Obviamente, não é super-relevante aqui, mas para a computação em geral há mais teclas mágicas por aí. O mais famoso é o Ctrl+ Alt+ Deleteno mundo do Windows, onde a combinação de teclas é muito próxima da mágica (pode ser usada para fazer o Windows funcionar, isso é bastante mágico por si só!), Já que é codificado no sistema para interromper e substituir praticamente tudo - muito semelhante SysRqnesse sentido.
KRyan

7
O Bash não usa o modo bruto - ele usa o modo caractere de cada vez, ou seja , cbreak/ -icanon, mas deixa o isigmodo definido e recebe sinais reais quando você pressiona as teclas mapeadas para eles. Ele lida SIGINTcom o comportamento como você descreveu (não apenas cancela a edição de linha, mas também cancela qualquer comando interno que possa estar em execução em um loop) e ignora completamente SIGTSTPe SIGQUIT. Outros programas, como o vi, podem não.
precisa saber é o seguinte

1
O @KRyan Ctrl+ Alt+ Deletecostumava ser ainda mais mágico do que é hoje - blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 . Embora eu seja uma pessoa com Linux no coração, fico bastante impressionado com a extensão em que o Windows tornou as coisas fáceis de usar e lógicas com recursos tão limitados nos primeiros dias.
Muzer # 8/17

Em alguns sistemas operacionais, mesmo que outro programa tenha o foco, o sistema (gerenciador de janelas, eu acho?) Realmente pressiona as teclas antes do emulador de terminal. Se você puder configurar atalhos de teclado para abrir janelas, abrir aplicativos, acionar scripts, antes que as teclas pressionadas sejam enviadas para o emulador de terminal, elas serão verificadas quanto a quaisquer atalhos que você configurou. E outro exemplo, se você não tiver aplicativos abertos ^c, não matará o gerenciador de janelas :). Não é capaz de comentário sobre o caráter cru / cozido em um material de tempo, mas a resposta está no local sobre como isso keystroke está gerandoSIGINT
Ajay

2
" modo cozido (porque não é cru)": estou ... sem palavras. Depois de todos esses anos, nunca fiz a conexão.
Isanae

8

^Cgeralmente é mapeado (veja stty -a) para o SIGINTsinal (veja man 7 signal).

Um não capturado SIGINTinterrompe o processo em execução, MAS ...

SIGINT é um dos sinais para os quais um processo pode especificar o comportamento ("Captura de um sinal").

O que você chama de "terminal" pega SIGINTe volta ao trabalho.


7

Quando eu era iniciante, estava faltando a parte que, quando estava usando a linha de comando, na verdade estava usando dois programas separados, um terminal e um shell (por exemplo, bash)

O shell é o que você provavelmente já conhece, um programa que usa como comandos ou scripts de entrada, os executa e imprime sua saída.

O terminal do outro lado é como um homem no meio entre o usuário e um programa (que geralmente é um shell como bash ou fish). O que o terminal faz é ler a entrada, por exemplo, do teclado, talvez processar essa entrada de alguma maneira e redirecioná-la para outro programa (bash).

Além disso, isso também funciona da outra maneira, quando o outro programa gera algo, que algo é redirecionado para o terminal, então é tarefa do terminal gerar esse algo para a tela. Entre a entrada e a impressão na tela, o terminal pode interpretar a entrada que está recebendo de várias maneiras.

Por exemplo, se um programa gerar a seguinte sequência:

\e[0;31m some extra foobar text

O terminal exibirá na tela "algum texto foobar extra" com letras vermelhas. Isso ocorre porque o terminal escolhe tratar esse código estranho de uma maneira especial, o que sugere que ele imprima a seguinte saída em vermelho.

Da mesma forma, quando o usuário pressiona Ctrl - C, a única coisa especial a respeito disso é que o terminal escolhe tratá-lo de uma maneira especial, não há nada de especial nessa sequência de teclas. Especificamente, isso sugere que ele envie o sinal de interrupção (SIGINT) para o processo que está sendo executado dentro do terminal, que é o shell. Se, nesse momento, existir algum programa que tenha sido gerado pelo shell e esteja sendo executado no primeiro plano, ele também receberá o sinal. Agora o shell possui um manipulador especial para esse sinal e nada acontece. Mas a maioria dos programas tem os manipuladores padrão que, no caso do SIGINT, acabam de sair.


5

Todo sinal tem uma ação padrão associada a ele. A ação padrão para um sinal é a ação que um script ou programa executa quando recebe um sinal.

Ctrl+ Cenvia o sinal "interrupção" ( SIGINT ), cujo padrão é finalizar o processo para o trabalho em execução em primeiro plano.

Ctrl+ Dinforma ao terminal que ele deve registrar um EOF na entrada padrão, que o bash interpreta como um desejo de sair .

Um processo pode optar por ignorar o sinal INT, e o Bash o faz quando está sendo executado no modo interativo.

Do manual :

Quando o bash é interativo, na ausência de interceptações, ele ignora o SIGTERM (para que matar 0 não mate um shell interativo) e o SIGINT é capturado e tratado (para que a espera incorporada seja interrompida). Em todos os casos, o bash ignora SIGQUIT. Se o controle do trabalho estiver em vigor, o bash ignorará SIGTTIN, SIGTTOU e SIGTSTP.


Entenda com armadilha :

trap é uma função embutida no shell que responde aos sinais de hardware e outros eventos. Ele define e ativa os manipuladores a serem executados quando o shell recebe sinais ou outras condições especiais.

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

-l imprima uma lista de nomes de sinais e seus números correspondentes.
-pexibir os comandos de interceptação associados a cada SIGNAL_SPEC.

arg deve ser lido e executado quando o shell receber sinal sigspec. Cada sigspec é um nome de sinal ou um número de sinal. Os nomes dos sinais não diferenciam maiúsculas de minúsculas e o prefixo SIG é opcional.

Se um sigspec for 0 ou EXIT , arg será executado quando o shell sair. Para entendê-lo, feche o terminal e abra-o após editar a seguinte linha no .bashrcarquivo.

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

Ctrl D é semelhante ao exitcomando para sair do terminal.

Se você deseja que o Bash saia ao receber o sinal INT, mesmo no modo interativo, você pode adicionar o seguinte ao seu ~/.bashrc:

trap 'exit' INT

ou

trap 'exit' 2

1
parece legítimo !!
Luv.preet 8/03
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.