Gestion des interruptions et sous-coquilles implicites dans les scripts shell

12

Disons que vous avez un script shell qui exécute une sorte de code de nettoyage via une EXITinterruption, comme ceci:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

trap mytrap exit

echo I am at the end of the script.

Comme prévu, cela s'affichera à la It's a trap!fin du script:

$ sh myscript
I am at the end of the script.
It's a trap!

Vous modifiez le script pour ajouter une fonction qui génère une sortie qui est finalement redirigée vers une autre commande, comme ceci:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

myfunc () {
  echo "I've got a bad feeling about this..."
}

trap mytrap exit

myfunc | cat > /dev/null

echo I am at the end of the script.

En raison du canal, le code dans myfuncest exécuté dans un sous-shell ... et les sous-coquilles ne semblent pas hériter du trapcomportement du parent, ce qui signifie que si vous effectuez ici des actions qui devraient être nettoyées par votre code d'interruption qui a gagné '' ça n'arrive pas.

Vous essayez donc ceci:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
}

Et il ne parvient toujours pas à se déclencher mytrapà la sortie du sous-shell. Il s'avère que vous avez besoin d'un explicite exit, comme ceci:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
  exit
}

Avec le code ci-dessus, mytrapse déclenchera de manière appropriée à la sortie du sous-shell:

$ sh myscript 
It's a trap!
I am at the end of the script.
It's a trap!

Est-ce un comportement attendu? J'ai été surpris par plusieurs choses ici:

  • trap les paramètres n'étaient pas hérités par les sous-coques
  • la sortie implicite d'un sous-shell ne semble pas déclencher un EXIT piège
larsks
la source

Réponses:

8

La commande bash trapintégrée autorise le mot clé RETURN. D'où le changement:

trap mytrap EXIT

à:

trap mytrap RETURN

Voir la discussion de trapdans shell-builtins

JRFerguson
la source