2012-03-09 4 views
121

Когда я использую команду exit в сценарии оболочки, сценарий завершает работу терминала (приглашение). Есть ли способ остановить скрипт, а затем остаться в терминале?Любой способ выйти из сценария bash, но не выйти из терминала

Ожидается, что мой сценарий run.sh будет выполняться непосредственно из источников или из другого сценария.

EDIT: Чтобы быть более точным, есть два сценария run2.sh, как

... 
. run.sh 
echo "place A" 
... 

и run.sh как

... 
exit 
... 

, когда я запускаю его . run2.sh, и если он ударил exit codeline в run.sh , Я хочу, чтобы он остановился до терминала и остался там. Но используя exit, весь терминал закрывается.

PS: Я пытался использовать return, но echo codeline все равно запускается на выполнение ....

+3

На самом деле, действительно, я должен спросить: почему вы используете exit в исходном сценарии? –

+3

команда выхода не должна прерывать сеанс терминала/логин. если вы используете 'exit 0' для завершения скрипта после успеха, когда вы запускаете свой скрипт ex:'./test.sh', вы должны увидеть результат, но консоль останется открытой. –

+0

Вы можете использовать команду 'shell', которая фактически открывает терминал оболочки. Однако мой собственный опыт заключается в том, что этого не происходит с 'exit'. Выход обычно возвращает элемент управления родительскому скрипту. –

ответ

173

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

Вместо использования exit вы хотите использовать return.

+1

Вот еще одно объяснение, которое я нашел полезным: http://askubuntu.com/a/53179/148337 – 3cheesewheel

+0

Хотя правильно, это не отличный ответ. Он игнорирует, что вызывающий скрипт может объявлять переменные или функции, к которым должен обращаться доступ к скрипту. Лучше объяснить, как установить код возврата, а затем обработать его в 'runs.sh' @ruakh, лучший ответ на этот вопрос. – MikeSchinkel

+3

Что делать, если функция является вложенным вызовом? то есть вызовы b, b вызывает c, c хочет немедленно выйти из a и b. – Michael

-2

1) выход 0 выйдет из сценария, если он успешен.

2) выход 1 выйдет из сценария, если это сбой.

Вы можете попробовать эти два вышеперечисленных основанных на ur req.

29

Да; вы можете использовать return вместо exit. Его основная цель - вернуться из функции оболочки, но если вы используете ее в скрипте source -d, он возвращается из этого скрипта.

В §4.1 "Bourne Shell Builtins" of the Bash Reference Manual ставит его:

 return [n] 

Причина Функция оболочки, чтобы выйти с возвращаемым значением п. Если n не прилагается, возвращаемое значение - это статус выхода последней команды, выполненной в функции . Это также может быть использован для завершения выполнения скрипта выполняется с . (или source) встроенными командами, возвращая либо п или статус выхода последней команды, выполненной в сценарии, как статус сценария выхода , Любая команда, связанная с ловушкой RETURN, выполняется до того, как выполнение возобновится после функции или скрипта. Состояние возврата не равно нулю, если return используется вне функции , а не во время выполнения скрипта . или source.

2

Это точно так же, как вы положили функцию запуска внутри вашего скрипта run2.sh. Вы используете код выхода внутри run, а источник - файл run2.sh в bash tty. Если придать функции запуска свою силу, чтобы выйти из вашего скрипта и дать run2.sh свою силу для выхода из терминатора. Тогда из-за функции запуска вы можете выйти из своего темнера.

#! /bin/sh 
    # use . run2.sh 

    run() 
    { 
     echo "this is run" 
     #return 0 
     exit 0 
    } 

    echo "this is begin" 
    run 
    echo "this is end" 

В любом случае, я одобряю с Kaz это проблема дизайна.

0

если ваш эмулятор терминала не -hold можно дезинфицировать в Sourced сценарий и удерживать терминал:

#!/bin/sh 
sed "s/exit/return/g" script >/tmp/script 
. /tmp/script 
read 

в противном случае вы можете использовать $TERM -hold -e script

2

Я думаю, что это происходит потому, что вы работаете он в режиме источника с точкой

. myscript.sh 

Вы должны работать, что в субоболочке:

/full/path/to/script/myscript.sh 

'источник' http://ss64.com/bash/source.html

+0

Вам не нужен полный путь к скрипту, если '. myscript.sh' работает. В лучшем случае вам может понадобиться './Myscript.sh'. –

0

Также убедитесь, что вернуться с ожидаемым значением возврата. Если вы используете exit, когда будете сталкиваться с выходом, он выйдет из вашей базовой оболочки, так как источник не создает другой процесс (экземпляр).

9

Вместо запуска кода с помощью . run2.sh вы можете запустить скрипт, используя sh run2.sh или bash run2.sh
будет открыт новый экземпляр для выполнения сценария, то он будет закрыт в конце сценария, оставляя другую оболочку открытым. `

+0

Если да, то почему второй параметр 'sh". " run2.sh'? – H0WARD

+0

@ H0WARD Ты прав, я забыл удалить точки. Теперь я отредактировал ответ. –

+0

OP явно указывает источник как требование. –

0

Правильно, что исходные и исполняемые сценарии используют return против exit, чтобы сохранить тот же сеанс открытым, как отмечали другие.

Это связанный совет, если вам когда-либо понадобится сценарий, который должен держать сеанс открытым, независимо от того, был он или нет.

Следующий пример может быть запущен как foo.sh или получен из источника . foo.sh/source foo.sh. В любом случае он будет держать сессию открытой после «выхода». Строка [email protected] передается так, чтобы функция имела доступ к аргументам внешнего скрипта.

#!/bin/sh 
foo(){ 
    read -p "Would you like to XYZ? (Y/N): " response; 
    [ $response != 'y' ] && return 1; 
    echo "XYZ complete (args [email protected])."; 
    return 0; 
    echo "This line will never execute."; 
} 
foo "[email protected]"; 

Терминал результат:

$ foo.sh
$ Вы хотели бы XYZ? (Y/N): n
$. foo.sh
$ Хотели бы вы XYZ?(Y/N): n
$ |
(терминальное окно остается открытым и принимает дополнительный вход)

Это может быть полезно для быстрого тестирования изменений сценария в одном терминале, сохраняя при этом кучу кода лома под основной exit/return в то время как вы работаете. Это также может сделать код более переносимым в некотором смысле (если у вас есть множество скриптов, которые могут или не могут быть вызваны по-разному), хотя это гораздо менее неудобно использовать return и exit, где это необходимо.

Смежные вопросы