Nouvelle réponse :
Cette question est beaucoup plus intéressante que je ne le pensais au départ. La réponse est essentiellement donnée ici :
Qu'advient-il d'un SIGINT (^C) lorsqu'il est envoyé à un script perl contenant des enfants ?
Voici la friandise pertinente. Je me rends compte que vous n'utilisez pas Perl, mais je suppose que Bash utilise la convention C.
La fonction système intégrée de Perl fonctionne exactement comme la fonction C system(3) de la bibliothèque C standard en ce qui concerne les signaux. Si vous utilisez la version Perl de system() ou pipe open ou backticks, alors le parent — le seul système appelant plutôt que celui appelé byit — IGNORERA tout SIGINT et SIGQUIT pendant que les enfants courent.
Cette explication est la meilleure que j'ai vue sur les différents choix qui peuvent être faits. Il indique également que Bash utilise l'approche WCE. Autrement dit, lorsqu'un processus parent reçoit SIGINT, il attend le retour de son processus enfant. Si ce processus géré est sorti d'un SIGINT, il se termine également avec SIGINT. Si l'enfant est sorti d'une autre manière, il ignore SIGINT.
Il existe également un moyen pour le shell appelant de savoir si le programme appelé s'est terminé sur SIGINT et s'il a ignoré SIGINT (ou l'a utilisé à d'autres fins). Comme dans la méthode WUE, le shell attend que l'enfant se termine. Il détermine si le programme s'est terminé sur SIGINT et si c'est le cas, il interrompt le script. Si le programme a effectué une autre sortie, le script se poursuivra. J'appellerai la manière de faire les "WCE" (pour "attente et sortie coopérative") pour la suite de ce document.
Je ne trouve pas de référence à cela dans la page de manuel de Bash, mais je continuerai à chercher dans les documents d'information. Mais je suis sûr à 99 % que c'est la bonne réponse.
Ancienne réponse :
Un état de sortie différent de zéro d'une commande dans un script Bash ne termine pas le programme. Si vous faites un echo $?
après ./script2.sh
il affichera 130. Vous pouvez terminer le script en utilisant set -e
comme le suggère phs.
$ help set
...
-e Exit immediately if a command exits with a non-zero status.
La deuxième partie de la réponse mise à jour de @ seanmcl est correcte et le lien vers http://www.cons.org/cracauer/sigint.html est vraiment bon à lire attentivement.
À partir de ce lien, "Vous ne pouvez pas "simuler" le bon état de sortie par un exit(3) avec une valeur numérique spéciale, même si vous recherchez la valeur numérique de votre système ". En fait, c'est ce qui est tenté dans le script2.sh de @Hermann Speiche.
Une solution consiste à modifier le gestionnaire de fonctions dans script2.sh comme suit :
function handler {
# ... do stuff ...
trap INT
kill -2 $$
}
Cela supprime efficacement le gestionnaire de signal et "relance" le SIGINT, provoquant la sortie du processus bash avec les indicateurs appropriés, de sorte que son processus bash parent gère ensuite correctement le SIGINT qui lui a été envoyé à l'origine. De cette façon, en utilisant set -e
ou tout autre hack n'est pas réellement nécessaire.
Il convient également de noter que si vous avez un exécutable qui se comporte de manière incorrecte lorsqu'il est envoyé un SIGINT (il n'est pas conforme à "Comment être un programme approprié" dans le lien ci-dessus, par exemple, il se termine avec un code de retour normal), une façon pour contourner ce problème, il suffit d'envelopper l'appel à ce processus avec un script comme celui-ci :
#!/bin/bash
function handler {
trap INT
kill -2 $$
}
trap handler INT
badprocess "[email protected]"