Por que o bash ignora o SIGTERM?

10

Às vezes, quando eu quero sair rapidamente, eu faço kill -15 -1. Notei que o bash está ignorando o SIGTERM.

Gostaria de saber qual é a lógica para esse comportamento bash ?

Não é muito UNIX'y ignorar o SIGTERM sem uma boa razão, não é?

ATUALIZAR:

mesmo (não) efeito para todos:

$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$

UPDATE2:

De man bash :

Quando o bash é interativo, na ausência de armadilhas, ele ignora o SIGTERM

Então é feito de propósito. Mas por que?

Michał Šrajer
fonte
Que matança você está usando? /bin/killou o shell embutido? Neste último caso, estou supondo que o shell não se mate com seu próprio componente.
terdon
@terdon: Eu costumava usar o builtin, mas não acho que esse seja o motivo para não se matar.
Michał Šrajer 20/02/2015
1
Se você quer sair rapidamente, em seguida, usar Ctrl + d
yomismo
1
@YoMismo: "sair da sessão X"
Michał Šrajer
2
@ MichałŠrajer: Ctrl-Alt-Backspace faz isso por mim no Xorg ... talvez você precise habilitá-lo no xorg.conf.
Laszlo Valko 21/02

Respostas:

10

Primeiro, isso não é específico para o bash. ATT ksh, dash e zsh se comportam da mesma maneira: eles ignoram SIGTERM e SIGQUIT durante a edição da linha de comando; quanto ao mksh, ele também não sai, mas os trata como SIGINT.

Tanto o manual do ksh quanto o manual do bash justificam ignorar o SIGTERM nestes termos:

para que kill 0não mate um shell interativo

kill 0mata todos os processos no grupo de processos em que o shell está¹. Em poucas palavras, o grupo de processos consiste em todos os processos em execução em primeiro plano em um terminal ou em todos os processos em segundo plano ou trabalho suspenso.

Mais precisamente, é isso o que acontece nas conchas modernas com controle de trabalho . Nessas conchas, kill 0não seria útil, pois o shell estaria em um grupo de processos próprio. Os shells mais antigos (ou shells modernos depois set +m) não criaram grupos de processos para comandos em segundo plano. Portanto, você pode usar o comando kill 0para eliminar todos os comandos em segundo plano sem desconectar-se kill 0.

No entanto, existem outras situações semelhantes nas quais tornar a concha imune é útil. Considere o caso em que você possui processos que monopolizam um terminal e deseja matá-los sem sair do sistema. Muitos sistemas possuem uma ferramenta como a pkillqual permite matar os processos em execução em um terminal. Você pode executar pkill -t $TTYou pkill -QUIT -t $TTYeliminar todos os processos em execução no terminal atual, exceto o shell que ignora o sinal.

Um shell normalmente desaparece quando o usuário o sai (com um comando como exitou logout) ou quando seu terminal sinaliza o final da entrada (o usuário pode causar isso pressionando Ctrl+ D) ou desaparece completamente. Neste último caso, o shell recebe o sinal SIGHUP, e não o ignora.

Para o seu caso de uso de logoff de uma sessão X, kill -15 -1será feito, pois mata o emulador de terminal que faz com que o shell receba o SIGHUP. De fato, é suficiente matar o servidor X, mas isso exige encontrar seu ID do processo. Se você deseja que o mesmo comando funcione em uma sessão de texto, você pode usá-lo kill -15 -1; exit. É um comando muito perigoso de ter ao seu alcance de qualquer maneira.

Seem Isso não parece ser mencionado nos manuais do shell como regra; é um recurso da chamada do sistema subjacente. É mencionado explicitamente na especificação POSIX .
² Atualmente, para fazer isso, execute jobs -la exibição de uma lista de tarefas com o ID do grupo de processos e depois kill -123 -456 …mate os grupos de processos.

Gilles 'SO- parar de ser mau'
fonte
5

Isso pode responder à sua pergunta:

Quando o Bash é interativo, na ausência de interceptações, ele ignora o SIGTERM (para que 'kill 0' não mate um shell interativo) e o SIGINT é capturado e tratado (para que a espera incorporada seja interrompida). Quando o Bash recebe um SIGINT, ele interrompe todos os loops em execução. Em todos os casos, o Bash ignora SIGQUIT. Se o controle de tarefas estiver em vigor (consulte Controle de tarefas), o Bash ignorará SIGTTIN, SIGTTOU e SIGTSTP.

Os comandos não integrados iniciados pelo Bash têm manipuladores de sinal configurados para os valores herdados pelo shell de seu pai. Quando o controle da tarefa não está em vigor, os comandos assíncronos ignoram SIGINT e SIGQUIT, além desses manipuladores herdados. Os comandos executados como resultado da substituição de comando ignoram os sinais de controle de tarefa gerados pelo teclado SIGTTIN, SIGTTOU e SIGTSTP.

O shell sai por padrão após o recebimento de um SIGHUP. Antes de sair, um shell interativo reenvia o SIGHUP para todos os trabalhos, em execução ou interrompidos. Os trabalhos interrompidos são enviados SIGCONT para garantir que eles recebam o SIGHUP. Para impedir que o shell envie o sinal SIGHUP para um trabalho específico, ele deve ser removido da tabela de trabalhos com o renegado incorporado (consulte Job Control Builtins) ou marcado para não receber SIGHUP usando disown -h.

Se a opção de shell huponexit tiver sido definida com shopt (consulte The Shopt Builtin), o Bash enviará um SIGHUP para todos os trabalhos quando um shell de logon interativo sair.

Se o Bash estiver aguardando a conclusão de um comando e receber um sinal para o qual uma captura foi configurada, a captura não será executada até que o comando seja concluído. Quando o Bash aguarda um comando assíncrono por meio da espera incorporada, a recepção de um sinal para o qual uma captura foi configurada fará com que a espera incorporada retorne imediatamente com um status de saída maior que 128, imediatamente após o qual a captura é executada.

FONTE : O manual GNU Bash

Petr
fonte
Eu citei isso na minha atualização2. O homem afirma que o bash está fazendo isso, mas não explica por que essa decisão. A questão permanece - por quê?
Michał Šrajer 20/02/2015