web-dev-qa-db-fra.com

Une alternative équivalente à Kinder / Gentler / subtler à Killall (par exemple "endall")?

Comment puis-je terminer tous les processus avec le même nom de manière plus douce que killall? Je ne veux pas interrompre les processus, mais leur laisser le temps de bien quitter.


Voir également:

Comment puis-je tuer les processus dans Ubuntu?

Dans le Moniteur système, quelle est la différence entre Kill Process et End Process?

Pourquoi killall (parfois?) Doit être appliqué deux fois?

tl; dr

16
nutty about natty

1. `killall` déjà Nice (SIGTERM)

killall envoie par défaut SIGTERM. C'est déjà l'approche de Nice qui laisse aux applications la possibilité de nettoyer elles-mêmes. Le "va mourir déjà, maintenant!" L’approche consiste à envoyer un signal SIGKILL, ce qui nécessite de spécifier cela en tant qu’option pour killall. De La GNU C Library: signaux de terminaison :

Macro: int SIGTERM

[...] C'est le moyen normal de poliment demander à un programme de se terminer.


2. "Processus de fin" de System Monitor également agréable (SIGTERM également)

Vous créez un lien vers une question sur GNOME System Monitor. Cela utilise également SIGTERM pour son action "End process" (et je réalise que je contredit la réponse à cette question). Vous pouvez le trouver dans le code source pour vous vérifier:

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>

Le 15 ici est le numéro de signal. Le signal 15 est SIGTERM. Et System Monitor a utilisé SIGTERM bien avant que cette autre question ne soit posée et répondue.


Addenda technique (en réponse à un commentaire)

En regardant à travers la représentation Github de git blame, voici les modifications apportées à la manière dont les signaux sont épelés dans le code source de GNOME System Monitor:

83007f2 24 juil. 2013 Code dupliqué remplacé pour l'envoi de signaux avec des paramètres GAction
e766b2d 18 juil. 2013 Menu contextuel du processus de port pour GAction
97674c79 3 Oct 2012 Supprimer la structure ProcData
8c5296c 3 juil. 2011 uniformisez l'indentation dans les fichiers source.

Aucune de celles-ci n'est passée de SIGQUIT à SIGTERM, et cette dernière date d'avant la question posée.

42
hvd

La réponse de @hvd est fondamentalement correcte. Pour sauvegarder cela encore plus, le processus init enverra d’abord SIGTERM aux processus lorsque vous éteignez votre ordinateur, puis, après un délai, enverra SIGKILL s’ils ne sont pas déjà sortis. Les processus ne peuvent pas gérer/ignorer SIGKILL.

Pour donner un peu plus de détails, la vraie réponse est que vous n’avez aucun moyen de savoir avec certitude que le programme le gère. SIGTERM est le signal le plus courant à utiliser pour demander poliment à un programme de quitter, mais la gestion du signal dépend du fait que le programme utilise quelque chose avec le signal.

En d'autres termes, si vous aviez un programme écrit par @Jos ou par @AlexGreg, ils manipuleraient probablement SIGQUIT mais probablement pas SIGTERM, et enverraient donc SIGTERM serait moins "souple" que SIGQUIT.

J'ai écrit du code pour que vous puissiez vous en servir vous-même. Enregistrez le fichier ci-dessous sous le nom signal-test.c, puis compilez-le avec

gcc -o signal-test signal-test.c

Vous pouvez ensuite l'exécuter ./signal-test et voir ce qui se passe lorsque vous envoyez différents signaux avec 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;
}

Dans l'état actuel des choses, le code gère à la fois SIGTERM et SIGQUIT. Vous pouvez essayer de commenter les lignes signal(SIG... (en utilisant // au début de la ligne) pour supprimer le gestionnaire de signaux, puis exécuter et renvoyer les signaux. Vous devriez pouvoir voir ces différentes sorties:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

selon que vous gérez les signaux ou non.

Vous pouvez également essayer d'ignorer les signaux:

signal(SIGTERM, SIG_IGN);

Si vous faites cela, alors envoyer SIGTERM ne fera rien, vous devrez utiliser SIGKILL pour terminer le processus.

Plus de détails dans man 7 signal. Notez que l'utilisation de signal() de cette manière est considérée comme non portable. C'est beaucoup plus simple que l'alternative!

Une autre note de bas de page mineure - sur Solaris killall tente de supprimer tous les processus. Tous. Si vous l'exécutez en tant que root, vous serez peut-être surpris :)

5
Roger Light

"Tout terminer" serait killall -s SIGQUIT [process name]. Si vous voulez une solution de fantaisie, définissez alias endall='killall -s SIGQUIT'.

2
Jos