Kinder / gentler / subtler equivalente alternativo a killall (ad esempio "endall")?

16

Come faccio a terminare tutti i processi con lo stesso nome in un modo più delicato rispetto a killall ? Non voglio interrompere i processi, ma lasciare loro il tempo per uscire correttamente.

Vedi anche:

Come posso eliminare i processi in Ubuntu?

In System monitor , qual è la differenza tra Kill Process e End Process?

Perché killall (a volte?) deve essere applicato due volte?

tl; dr

    
posta nutty about natty 21.09.2015 - 15:23

3 risposte

42

1. 'killall' già carino (SIGTERM)

killall per impostazione predefinita invia SIGTERM . Questo è già il buon approccio che lascia alle applicazioni la possibilità di ripulire se stessi. Il "vai morire già, proprio ora!" approccio è quello di inviare un segnale SIGKILL , che richiede di specificarlo come opzione a killall . Da Libreria GNU C: Segnali di terminazione :

  

Macro: int SIGTERM

     

[...] È il modo normale per cortesemente chiedere a un programma di terminare.

2. "End process" di System Monitor è altrettanto piacevole (anche SIGTERM)

Ti colleghi a una domanda su GNOME System Monitor. Questo usa SIGTERM anche per la sua azione "Fine processo" (e mi rendo conto di contraddire la risposta a questa domanda). Puoi trovarlo nel codice sorgente per verificare te stesso:

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>

Il 15 qui è il numero del segnale. Il segnale 15 è SIGTERM . E System Monitor ha utilizzato SIGTERM molto prima che l'altra domanda sia stata fatta e abbia risposto.

Addendum tecnico (in risposta a un commento)

Guardando attraverso la rappresentazione Github di git blame , ecco le modifiche che sono state apportate a come i segnali sono enunciati nel codice sorgente di GNOME System Monitor:

383007f2 24 luglio 2013 Sostituito il codice duplicato per l'invio di segnali con i parametri di GAction < br> 0e766b2d 18 lug 2013 Menu a discesa del processo porta a GAction
97674c79 3 ott 2012 Elimina la struttura ProcData
38c5296c 3 lug 2011 Rendi uniforme l'indentazione sui file sorgente.

Nessuno di questi è cambiato da SIGQUIT a SIGTERM , e l'ultimo era precedente alla domanda collegata.

    
risposta data hvd 21.09.2015 - 15:49
5

La risposta di @hvd è fondamentalmente corretta. Per sostenere ancora di più, il processo init invierà prima SIGTERM ai processi quando stai spegnendo il tuo computer, quindi dopo un ritardo invierai SIGKILL se non sono già usciti. I processi non possono gestire / ignorare SIGKILL .

Per dare un po 'più di dettaglio, la vera risposta è che non hai modo di sapere con certezza che il programma lo gestisce. SIGTERM è il segnale più usuale da usare per chiedere educatamente un programma di uscire, ma la gestione del segnale dipende dal programma che fa qualcosa con il segnale.

Per dirla in modo diverso, in base alle altre risposte, se avessi un programma scritto da @Jos o da @AlexGreg, presumibilmente gestiranno SIGQUIT ma probabilmente non SIGTERM , e quindi invieremo SIGTERM sarebbe meno "soft" di SIGQUIT .

Ho scritto del codice in modo da poterlo giocare da solo. Salva il sotto come signal-test.c , quindi compila con

gcc -o signal-test signal-test.c

Puoi quindi eseguirlo ./signal-test e vedere cosa succede quando invii segnali diversi con 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;
}

Allo stato attuale, il codice gestisce sia SIGTERM che SIGQUIT con garbo. Potresti provare a commentare le linee signal(SIG... (usando un // all'inizio della riga) per rimuovere il gestore di segnale, quindi eseguire e inviare nuovamente i segnali. Dovresti essere in grado di vedere questi diversi output:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

a seconda che tu gestisca i segnali o meno.

Puoi anche provare a ignorare i segnali:

signal(SIGTERM, SIG_IGN);

Se lo fai, l'invio di SIGTERM non farà nulla, dovrai utilizzare SIGKILL per terminare il processo.

Ulteriori dettagli in man 7 signal . Tieni presente che l'utilizzo di signal() in questo modo è considerato non trasferibile, tuttavia è molto più semplice dell'alternativa!

Un'altra piccola nota a piè di pagina - su Solaris killall tenta di uccidere tutti i processi. Tutti loro. Se lo esegui come root, potresti essere sorpreso:)

    
risposta data Roger Light 21.09.2015 - 18:56
2

"End all" sarebbe killall -s SIGQUIT [process name] . Se vuoi una soluzione di fantasia, definisci alias endall='killall -s SIGQUIT' .

    
risposta data Jos 21.09.2015 - 15:29

Leggi altre domande sui tag