Kinder / gentler / subtler alternativa equivalente a killall (por exemplo, “endall”)?

16

Como termino todos os processos com o mesmo nome de uma maneira mais suave do que o killall ? Eu não quero interromper os processos, mas deixe-os tempo para sair corretamente.

Veja também:

Como faço para matar processos no Ubuntu?

No monitor do sistema , qual é a diferença entre o processo Kill e o processo final?

Por que o killall (às vezes?) precisa ser aplicado duas vezes?

tl; dr

    
por nutty about natty 21.09.2015 / 15:23

3 respostas

42

1. 'killall' já é legal (SIGTERM)

Por padrão,

killall envia SIGTERM . Esta é a a abordagem agradável que deixa as aplicações a chance de limpar depois de si. O "vai morrer já, agora mesmo!" A abordagem é enviar um sinal SIGKILL , que requer que seja especificado como uma opção para killall . De A Biblioteca GNU C: Sinais de Rescisão :

  

Macro: int SIGTERM

     

[...] É a maneira normal de educadamente solicitar que um programa termine.

2. O "processo final" do Monitor do Sistema é igualmente bom (SIGTERM também)

Você faz um link para uma pergunta sobre o GNOME System Monitor. Isso também usa SIGTERM para a ação "Finalizar processo" (e percebo que estou contradizendo a resposta a essa pergunta). Você pode encontrá-lo no código-fonte para verificar a si mesmo:

data / menus.ui :

<item>
  <attribute name="label" translatable="yes">_End</attribute>
  <attribute name="action">win.send-signal-end</attribute>
  <attribute name="accel">&lt;Primary&gt;e</attribute>
  <attribute name="target" type="i">15</attribute>
</item>

Os 15 aqui são o número do sinal. O sinal 15 é SIGTERM . E o System Monitor usou SIGTERM bem antes que outra questão fosse perguntada e respondida.

Adendo técnico (em resposta a um comentário)

Examinando a representação do git blame no Github, aqui estão as mudanças que foram feitas no modo como os sinais são escritos no código-fonte do GNOME System Monitor:

383007f2 24 de julho de 2013 Substitui o código duplicado por enviar sinais com parâmetros de GA < br> 0e766b2d 18 de julho de 2013 Menu pop-up de processo de porta para o GAction
97674c79 3 de outubro de 2012 Livrar-se da estrutura ProcData | 38c5296c 3 Jul 2011 Torne uniforme de indentação nos arquivos de origem.

Nenhum destes mudou de SIGQUIT para SIGTERM , e esse último foi de antes da pergunta vinculada ser feita.

    
por hvd 21.09.2015 / 15:49
5

A resposta de @hvd está basicamente correta. Para comprovar ainda mais, o processo init primeiro enviará SIGTERM para os processos quando você estiver desligando o computador e, depois de um atraso, enviará SIGKILL se eles ainda não tiverem saído. Os processos não podem manipular / ignorar SIGKILL .

Para dar um pouco mais de detalhes, a verdadeira resposta é que você não tem como saber com certeza se o programa lida com isso. SIGTERM é o sinal mais comum para pedir educadamente que um programa seja encerrado, mas todo o tratamento do sinal depende do programa fazer algo com o sinal.

De maneira diferente, com base nas outras respostas, se você tivesse um programa escrito por @Jos ou por @AlexGreg, eles presumivelmente lidariam com SIGQUIT , mas possivelmente não com SIGTERM e, portanto, enviando SIGTERM seria menos "soft" do que SIGQUIT .

Eu escrevi um código para você brincar sozinho. Salve o abaixo como signal-test.c e, em seguida, compile com

gcc -o signal-test signal-test.c

Você pode executar ./signal-test e ver o que acontece quando você envia sinais diferentes com killall -s <signal> .

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int flag = 0;

void handle_signal(int s)
{
    flag = s;
}

int main(int argc, char *argv[])
{
    signal(SIGTERM, handle_signal);
    signal(SIGQUIT, handle_signal);

    while(flag == 0){
        sleep(1);
    }
    printf("flag is %d\n", flag);
    return flag;
}

Como está, o código manipula SIGTERM e SIGQUIT normalmente. Você poderia tentar comentar as linhas signal(SIG... (usando // no início da linha) para remover o manipulador de sinal, então execute e envie os sinais novamente. Você deve poder ver estas saídas diferentes:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

dependendo se você lida com os sinais ou não.

Você também pode tentar ignorar os sinais:

signal(SIGTERM, SIG_IGN);

Se você fizer isso, enviar SIGTERM não fará nada, você terá que usar SIGKILL para finalizar o processo.

Mais detalhes em man 7 signal . Note que usar signal() desta forma é considerado não portátil - é muito mais fácil do que a alternativa!

Uma outra nota de rodapé secundária - no Solaris killall tenta matar todos os processos. Todos eles. Se você executá-lo como root, então você pode se surpreender:)

    
por Roger Light 21.09.2015 / 18:56
2

"End all" seria killall -s SIGQUIT [process name] . Se você quiser uma solução sofisticada, defina alias endall='killall -s SIGQUIT' .

    
por Jos 21.09.2015 / 15:29