GNU/Linux >> Tutoriels Linux >  >> Linux

Bash :Pourquoi le script parent ne se termine-t-il pas sur SIGINT lorsque le script enfant piège SIGINT ?

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]"

Linux
  1. Pourquoi le script Bash ne se ferme-t-il pas après l'exécution ?

  2. Pourquoi le fichier de traduction Bash ne contient-il pas tous les textes d'erreur ?

  3. La commande Rm dans le script Bash ne fonctionne pas avec la variable ?

  4. N'importe quel moyen de quitter le script bash, mais sans quitter le terminal

  5. Que signifie set -e dans un script bash ?

Pourquoi la saisie semi-automatique ne fonctionne-t-elle pas lors de la saisie d'un nom de commande après `source` ?

Pourquoi le parent Shell Here-document ne fonctionne pas pour la sous-commande dans Dash mais Bash fonctionne?

Pourquoi `exit &` ne fonctionne pas ?

Le processus enfant reçoit le SIGINT du parent

Pourquoi ce pipeline shell sort-il ?

pourquoi supprimer l'historique bash n'est pas suffisant?