web-dev-qa-db-fra.com

quitter la pile de fonctions sans quitter le shell

J'écrivais un script et j'ai rencontré un problème étrange. Si je source un script qui contient un tas de fonctions qui peuvent appeler une fonction d'erreur qui produit une chaîne puis se ferme, il quittera mon shell. Je sais pourquoi il le fait. C'est parce qu'un appel de fonction se trouve dans le même espace de processus que l'appelant (au moins, il est en bash), donc la sortie dans la fonction met fin au 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]

Ma question est donc la suivante: puis-je quitter toutes les fonctions de la pile de fonctions sans terminer le shell actuel et sans générer un nouveau sous-shell?

Merci

36
Adrian

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

kill -INT $$

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


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

34
Adrian

tu peux 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
}
9
pizza

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

Alternativement, vous pouvez définir fn comme un script Shell, afin que exit fasse ce que vous voulez (sauf si un fork est trop cher).

6
l0b0

en utilisant l'instruction return, mais vous devez ajouter return après avoir appelé error

2
Nahuel Fouilleul

Le shell n'a pas vraiment de mécanisme d'exception pour rembobiner à travers de nombreux appels de fonction à la fois. Vous devez simplement vérifier les valeurs de retour et revenir manuellement jusqu'en bas.

2
Mark Reed