Por que o bash ignora o SIGTERM?

9

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

Eu me pergunto qual é a razão para tal comportamento bash ?

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

ATUALIZAÇÃO:

mesmo efeito (sem) para todos:

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

UPDATE2:

De homem bash :

When bash is interactive, in the absence of any traps, it ignores SIGTERM

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

    
por Michał Šrajer 20.02.2015 / 12:52

2 respostas

9

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 trata-os como SIGINT.

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

so that kill 0 does not kill an interactive shell

kill 0 mata todos os processos no grupo de processos que o shell está em. 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 um plano de fundo ou em um trabalho suspenso.

Mais precisamente, é isso que acontece nos shells modernos com controle de trabalho . Em tais shells, kill 0 não seria útil, pois o shell estaria em um grupo de processos próprio. Conchas mais antigas (ou shells modernas depois de set +m ) não criavam grupos de processos para comandos em segundo plano. Assim, você poderia usar o comando kill 0 para matar todos os comandos de segundo plano sem sair do site.² Assim, o kill 0 rationale parece um antigo que não é mais justificado atualmente, mas mantido para compatibilidade com versões anteriores.

No entanto, existem outras situações semelhantes em que tornar o shell imune é útil. Considere o caso em que você tem processos monopolizando um terminal e quer matá-los sem ter logado. Muitos sistemas têm uma ferramenta como pkill que permite eliminar os processos em execução em um terminal. Você pode executar pkill -t $TTY ou pkill -QUIT -t $TTY para eliminar todos os processos em execução no terminal atual, exceto o shell que ignora o sinal.

Um shell normalmente desaparece quando o usuário sai dele (com um comando como exit ou 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 logout de uma sessão X, kill -15 -1 irá fazê-lo, já que ele mata o emulador de terminal que faz com que o shell receba SIGHUP. Na verdade, é suficiente matar o servidor X, mas isso requer encontrar seu ID de processo. Se você quiser que o mesmo comando funcione em uma sessão de texto, use kill -15 -1; exit . Isso é um comando bastante perigoso para ter na ponta dos dedos de qualquer maneira.

¹ Isto não parece ser mencionado nos manuais de shell como regra; é um recurso da chamada do sistema subjacente. É mencionado explicitamente na especificação POSIX .
² Atualmente, para fazer isso, execute jobs -l para ver uma lista de jobs com seus IDs de grupos de processos, e então kill -123 -456 … para eliminar os grupos de processos.

    
por 21.02.2015 / 01:33
5

Isso pode responder à sua pergunta:

When Bash is interactive, in the absence of any traps, it ignores SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin is interruptible). When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT. If job control is in effect (see Job Control), Bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.

Non-builtin commands started by Bash have signal handlers set to the values inherited by the shell from its parent. When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers. Commands run as a result of command substitution ignore the keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Job Control Builtins) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt (see The Shopt Builtin), Bash sends a SIGHUP to all jobs when an interactive login shell exits.

If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.

SOURCE : O manual do GNU Bash

    
por 20.02.2015 / 14:08

Tags