Как полностью перезапустить скрипт изнутри самого скрипта

22

Я настраиваю скрипт оболочки с меню и подменю, параметрами и т. Д. Но в каждом меню / подменю / и т. Д. Мне нужен выбор «Вернуться в главное меню».

Я уже настроил меню, и оно работает нормально, но мне нужен способ, чтобы просто перезапустить скрипт с нуля, сбросить все переменные и т. Д. И т. Д.

Или способ выйти из текущего скрипта и запустить его снова.

Я пытался сделать это:

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

Но это запускает «новый» скрипт внутри «старого» скрипта, поэтому, когда я выхожу из «нового» скрипта, он возвращается к «старому» скрипту (если это имеет смысл). Это сценарий внутри сценария.

Кто-нибудь получил идею, как его полностью перезапустить?

Moonbloom
источник
Это должно быть так $ScriptLocили иначе: ./ScriptLocищет скрипт с таким именем в текущем каталоге.
пул

Ответы:

10

Вы можете использовать что-то вроде этого:

$(basename $0) && exit

$(basename $0)создаст новый экземпляр текущего скрипта и exitвыйдет из текущего экземпляра скрипта.

Вот тестовый скрипт, который выделяет вышеуказанный метод:

#!/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"

Если вы не используете export count=0(что делает countпеременную окружения) и используете только count=0(что делает contпеременную локального сценария), то сценарий никогда не остановится.

Раду Рэдяну
источник
&& exitвыйдет, только если скрипт завершится успешно. Так, если, например, скрипт не является исполняемым или имеет синтаксическую ошибку, это, скорее всего, будет вращаться.
пул
Добавлен ./ к базовому имени - иначе красивое решение - действительно приятно, def +1.
Левша Дж. Балог
4

Надежно получить сценарий, который в данный момент выполняется, сложнее, чем вы думаете. См. Http://mywiki.wooledge.org/BashFAQ/028 .

Вместо этого вы можете сделать что-то вроде этого:

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

По сути, вы запускаете функцию main_menu в подоболочке, поэтому, если вы выходите из main_menu или из любого подменю, вы выходите из подоболочки, а не из основной оболочки. статус выхода 255 выбран здесь, чтобы означать «идти снова». Любое другое состояние выхода выйдет из бесконечного цикла.

geirha
источник