Comment redémarrer complètement le script depuis l'intérieur du script lui-même

22

Je mets en place un script shell avec des menus et sous-menus, des options, etc. Mais sur chaque menu / sous-menu / etc, j'ai besoin d'un choix "Retour au menu principal".

J'ai déjà configuré le menu et cela fonctionne bien, mais j'ai besoin d'un moyen de redémarrer simplement le script à partir de zéro, de réinitialiser toutes les variables, etc., etc.

Ou un moyen de quitter le script actuel et de le redémarrer.

J'ai essayé de faire ça:

ScriptLoc=$(readlink -f "$0")
./ScriptLoc

Mais cela démarre le "nouveau" script à l'intérieur de l '"ancien" script, donc quand je quitte le "nouveau" script, il revient au "vieux" script (si cela a un sens). C'est un script dans une sorte de script.

Quelqu'un a une idée de comment le redémarrer complètement?

Moonbloom
la source
Cela devrait être de $ScriptLoctoute façon: ./ScriptLocrecherche un script de ce nom dans le répertoire courant.
poolie

Réponses:

10

Vous pouvez utiliser quelque chose comme ceci:

$(basename $0) && exit

$(basename $0)va créer une nouvelle instance du script en cours et exitquittera l'instance actuelle du script.

Voici un script de test qui met en évidence la méthode ci-dessus:

#!/bin/bash

if ! [[ $count =~ ^[0-9]+$ ]] ; then
    export count=0
fi

echo $count

if [ $count -le 10 ]; then
    count=$(echo "$count+1" | bc)   
    ./$(basename $0) && exit #this will run if started from the same folder
fi

echo "This will be printed only when the tenth instance of script is reached"

Si vous n'utilisez pas export count=0(qui font countpour être une variable d'environnement) et utilisez seulement count=0(qui font contune variable de script locale), alors le script ne s'arrêtera jamais.

Radu Rădeanu
la source
&& exitne se fermera que si le script réussit. Donc, si par exemple le script n'est pas exécutable ou a une erreur de syntaxe, cela risque de tourner.
poolie
Ajouté ./ au nom de base - sinon une belle solution - vraiment sympa, def a +1.
Lefty G Balogh
4

Obtenir de manière fiable le script en cours d'exécution est plus difficile que vous ne le pensez. Voir http://mywiki.wooledge.org/BashFAQ/028 .

Au lieu de cela, vous pouvez faire quelque chose comme ceci:

main_menu() { 
    printf '1. Do something cool\n'
    printf '2. Do something awesome\n'
    : ... etc
}

some_sub_sub_menu() {
    ...
    printf 'X. Return to main menu\n'
    ...
    if [[ $choice = [Xx] ]]; then
        exit 255
    fi
}

while true; do
    (main_menu)
    res=$?
    if (( res != 255 )); then
        break
    fi
done

Fondamentalement, vous exécutez la fonction main_menu dans un sous-shell, donc si vous quittez le main_menu, ou l'un des sous-menus, vous quittez le sous-shell, pas le shell principal. l'état de sortie 255 est choisi ici pour signifier "recommencer". Tout autre état de sortie sortira de la boucle par ailleurs infinie.

geirha
la source