quitter la pile de fonctions sans quitter le shell

J'écrivais un script et je suis tombé sur un problème étrange. Si je source un script qui contient un tas de fonctions qui peuvent appeler une fonction d'erreur qui sort une chaîne puis se ferme, il quittera mon shell. Je sais pourquoi il le fait. C'est parce qu'un appel de fonction est dans le même espace de processus que l'appelant (au moins il est dans bash), donc la sortie dans la fonction termine le processus en cours avec le code de sortie fourni. Exemple:

error()
{
  echo $1
  exit 1
}

fn()
{
  if [ $# == 0 ]; then
    error "Insufficient parameters."
  fi
  # do stuff
}

$ fn
Insufficient parameters.
[shell terminates]

Donc ma question Est, puis-je quitter tout fonctions dans la pile de fonctions sans terminer le shell actuel et sans générer un nouveau sous-shell?

Merci

29
demandé sur Adrian 2012-06-21 19:06:46

5 réponses

Pour quitter la pile de fonctions sans quitter le shell, on peut utiliser la commande:

kill -INT $$

Comme l'a déclaré pizza , c'est comme appuyer sur Ctrl-C, ce qui arrêtera l'exécution du script en cours et vous déposera à l'invite de commande.

 

 


Note: la seule raison pour laquelle je n'ai pas sélectionné la réponse de pizza est que cela a été enterré dans sa réponse et n'a pas répondu directement.

31
répondu Adrian 2017-05-23 12:17:41

, Vous pouvez faire un

exit() { return $1;}

Puis

source ./your_script 

En réponse aux sceptiques, cela n'affecte que le shell actuel, cela n'affecte pas les shells que vous générez.

La forme la plus informative peut être

exit() {
    local ans
    local line
    read -p "You really want to exit this? " line
    ans=$(echo $line)
    case "$ans" in
            Y);;
            y);;
            *)kill -INT $$;;
    esac
    unset -f exit
    exit $1
}
7
répondu pizza 2012-06-25 21:05:47

Vous devrez ajouter des instructions return à chacune de vos fonctions pour vérifier la valeur de retour de toutes les fonctions qu'elles appellent à leur tour. Sourcing un fichier est comme couper et coller le code dans le contexte actuel, à l'exception mineure des variables comme $BASH_SOURCE.

Vous pouvez également définir fn comme un script shell, de sorte que exit fera ce que vous voulez (sauf si un fork est trop cher).

5
répondu l0b0 2012-06-21 15:30:59

En utilisant return instruction, mais vous devez ajouter return après l'erreur d'appel

2
répondu Nahuel Fouilleul 2012-06-22 04:40:46

Le shell n'a pas vraiment de mécanisme d'exception pour le rembobinage à travers de nombreux appels de fonction à la fois. Vous devez simplement vérifier les valeurs de retour et retourner manuellement tout le chemin vers le bas.

1
répondu Mark Reed 2012-06-21 15:22:37