J'essaie de mettre en place un script shell pour qu'il exécute des processus d'arrière-plan, et quand je Ctrlcle script shell, il tue les enfants, puis se ferme.
Le meilleur que j'ai réussi à trouver est celui-ci. Il semble que lekill 0 -INT
tue également le script avant l'attente, de sorte que le script shell meurt avant la fin des enfants.
Toutes les idées sur la façon dont je peux faire attendre ce script shell pour que les enfants meurent après l'envoi INT
?
#!/bin/bash
trap 'killall' INT
killall() {
echo "**** Shutting down... ****"
kill 0 -INT
wait # Why doesn't this wait??
echo DONE
}
process1 &
process2 &
process3 &
cat # wait forever
Réponses:
Votre
kill
commande est à l'envers.Comme de nombreuses commandes UNIX, les options commençant par un moins doivent venir en premier, avant les autres arguments.
Si vous écrivez
il voit l'
-INT
option comme une option et envoieSIGINT
à0
(0
est un nombre spécial signifiant tous les processus dans le groupe de processus actuel).Mais si vous écrivez
il voit le
0
, décide qu'il n'y a plus d'options, donc utiliseSIGTERM
par défaut. Et envoie cela au groupe de processus actuel, comme si vous l'aviez fait(il essaierait également d'envoyer
SIGTERM
à-INT
, ce qui provoquerait une erreur de syntaxe, mais il enverraitSIGTERM
à0
premier, et n'atteint jamais aussi loin.)Donc, votre script principal obtient un
SIGTERM
avant de pouvoir exécuter lewait
etecho DONE
.Ajouter
au sommet, juste après
et l'exécuter à nouveau pour le prouver.
Comme le souligne Stéphane Chazelas, vos enfants issus de milieux (
process1
, etc.) ignorerontSIGINT
par défaut.En tout cas, je pense que l'envoi
SIGTERM
aurait plus de sens.Enfin, je ne sais pas s'il
kill -process group
est garanti d'aller en premier aux enfants. Ignorer les signaux lors de l'arrêt peut être une bonne idée.Essayez donc ceci:
la source
Malheureusement, les commandes démarrées en arrière-plan sont définies par le shell pour ignorer SIGINT, et pire, elles ne peuvent pas le ignorer avec
trap
. Sinon, il vous suffirait de faireParce que process1 et process2 obtiendraient le SIGINT lorsque vous appuyez sur Ctrl-C car ils font partie du même groupe de processus qui est le groupe de processus de premier plan du terminal.
Le code ci-dessus fonctionnera avec pdksh et zsh qui à cet égard ne sont pas conformes à POSIX.
Avec d'autres shells, vous devrez utiliser autre chose pour restaurer le gestionnaire par défaut pour SIGINT comme:
ou utilisez un signal différent comme SIGTERM.
la source
Pour ceux qui veulent simplement tuer un processus et attendre qu'il meure, mais pas indéfiniment :
Il attend max 60 secondes par type de signal.
Avertissement: Cette réponse n'est en aucun cas liée à la capture d'un signal de mise à mort et à sa distribution.
Il sélectionne l'application à tuer par son nom ou ses arguments. Conservez les crochets pour la première lettre du nom de l'application pour éviter de faire correspondre grep lui-même.
Avec certaines modifications, vous pouvez utiliser directement le PID ou un simple
pidof process_name
au lieu de l'ps
instruction.Détails du code: le grep final consiste à obtenir le PID sans les espaces de fin.
la source
Si vous souhaitez gérer certains processus d'arrière-plan, pourquoi ne pas utiliser les fonctionnalités de contrôle des tâches bash?
la source
J'ai donc aussi bricolé avec ça. Dans Bash, vous pouvez définir des fonctions et faire des choses fantaisistes avec celles-ci. Mes collègues et moi utilisons
terminator
, donc pour les exécutions par lots, nous générons normalement tout un tas de fenêtres de terminaison si nous voulons afficher la sortie (moins élégant que lestmux
onglets, mais vous pouvez utiliser une interface plus proche de l'interface graphique haha).Voici la configuration que j'ai trouvée, ainsi qu'un exemple de choses que vous pouvez exécuter:
L'exécuter
Modifiez @Maxim, je viens de voir votre suggestion, cela rend les choses plus simples! Merci!
la source