2009-12-11 15:24:17 +0000 2009-12-11 15:24:17 +0000
302
302

В чем разница между выполнением Bash-скрипта и его поиском?

В чем разница между выполнением Bash-скрипта типа A и поиском Bash-скрипта типа B?

A
> ./myscript

B
> source myscript

Ответы (6)

369
369
369
2010-08-16 21:58:48 +0000

Источник скрипт будет выполнять команды в процессе current shell.

Executing скрипт будет выполнять команды в процессе new shell.

Использовать исходный код, если вы хотите, чтобы скрипт изменил окружение в запущенной оболочке. Использовать выполнить по-другому.

Если вы все еще запутались, пожалуйста, прочтите дальше.

Терминология

Чтобы прояснить некоторые распространенные путаницы с синтаксисом выполнения и синтаксисом исходного кода:

./myscript

Это будет исполняться myscript при условии, что файл является исполняемым и расположен в текущем каталоге. Ведущая точка и косая черта (./) обозначают текущую директорию. Это необходимо, потому что текущий каталог обычно не находится (и обычно не должен находиться) в $PATH.

myscript

Это будет исполняться myscript, если файл является исполняемым и расположен в какой-то директории в $PATH.

source myscript

Это будет источник myscript. Файл не обязательно должен быть исполняемым, но это должен быть корректный скрипт оболочки. Файл может быть в текущем каталоге или в каталоге $PATH.

. myscript

Это также источник myscript. Это “написание” является официальным, как определено в POSIX . Бэш определил source как псевдоним к точке.

Демонстрация

Рассмотрим myscript.sh со следующим содержанием:

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

Прежде чем мы выполним скрипт сначала, мы проверим текущее окружение:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Переменная FOO не определена, и мы находимся в домашней директории.

Теперь мы исполняем файл:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Проверьте окружение еще раз:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Переменная FOO не установлена, и рабочий каталог не изменился.

Вывод скрипта четко показывает, что переменная была установлена, а каталог изменен. Проверка после этого показывает, что переменная не установлена и каталог не изменился. Что произошло? Изменения были сделаны в оболочке new. Оболочка current создала оболочку new для выполнения скрипта. Скрипт выполняется в новой оболочке, и все изменения в окружении вступают в силу в новой оболочке. После выполнения скрипта новая оболочка уничтожается. Все изменения окружения в новой оболочке уничтожаются в новой оболочке. В текущей оболочке распечатывается только выходной текст.

Теперь мы источник файла:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Снова проверка окружения:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

Переменная FOO установлена, а рабочий каталог изменился.

Источник скрипта не создает новую оболочку. Все команды выполняются в текущей оболочке, и изменения среды вступают в силу в текущей оболочке.

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

Другая демонстрация

Рассмотрим следующий скрипт pid.sh:

#!/bin/sh
echo $$

(специальная переменная $$ расширяется до PID текущего процесса выполнения оболочки)

Сначала распечатайте PID текущей оболочки:

$ echo $$
25009

Источник скрипта:

$ source pid.sh
25009

Выполнить сценарий, обратите внимание на PID:

$ ./pid.sh
25011

Источник снова:

$ source pid.sh
25009

Выполнить снова:

$ ./pid.sh
25013

Вы можете видеть, что поиск источников сценарий запускается в том же самом процессе во время выполнения сценария создает новый процесс каждый раз. Этим новым процессом является new shell, который был создан для выполнения скрипта. Источник скрипта не создает новую оболочку и, таким образом, PID остается прежним.

Сводка

Как поиск, так и выполнение скрипта будут выполнять команды в скрипте построчно, как если бы вы набирали эти команды от руки построчно.

Разница в том, что:

  • Когда вы execute открываете скрипт new shell, набираете команды в новом shell'е, копируете результат обратно в вашу текущую оболочку, затем закрываете новую оболочку. Любые изменения окружения вступят в силу только в новой оболочке и будут потеряны, как только новая оболочка будет закрыта.
  • Когда вы набираете source скрипт, вы набираете команды в current shell. Любые изменения окружения вступят в силу и останутся в вашей текущей оболочке.

Используйте исходный код, если вы хотите, чтобы скрипт изменил окружение в текущей оболочке. Используйте другое выполнение.


Смотрите также:

23
23
23
2009-12-11 15:35:56 +0000

Выполнение скрипта запускает его в отдельном дочернем процессе, т.е. для обработки скрипта вызывается отдельный экземпляр оболочки. Это означает, что любые переменные окружения и т.д., определенные в скрипте _ не могут_ быть обновлены в родительском (текущем) shell'е.

Источник скрипта означает, что он анализируется и выполняется самой текущей оболочкой. Как будто вы набираете содержимое скрипта. По этой причине исходный скрипт не обязательно должен быть исполняемым. Но он должен быть исполняемым, если вы его выполняете.

Если у вас есть позиционные аргументы в текущей оболочке, они не изменяются.

Итак, если у меня есть файл a.sh, содержащий:

echo a $*

, то у меня есть:

$ set `date`
$ source ./a.sh

Я получаю что-то вроде:

a Fri Dec 11 07:34:17 PST 2009

В то время как..:

$ set `date`
$ ./a.sh

дает мне:

a

Надежда, которая помогает.

9
9
9
2009-12-11 15:27:08 +0000

Источник, по сути, тот же самый, что и ввод каждой строки скрипта в командной строке по одному в командной строке…

Execution запускает новый процесс, а затем запускает каждую строку скрипта, изменяя только текущее окружение тем, что оно возвращает.

6
6
6
2012-02-23 07:27:43 +0000

В дополнение к вышесказанному, выполнение скрипта как ./myscript требует разрешения на выполнение файла myscript, в то время как sourcing не требует никаких разрешений на выполнение. Вот почему chmod +x myscript не требуется до source myscript.

5
5
5
2009-12-11 15:25:38 +0000

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

2
2
2
2015-03-27 14:04:20 +0000

Команда source выполняет предоставленный сценарий (разрешение на исполнение не обязательно ) в текущей оболочке, в то время как ./ выполняет предоставленный сценарий **executable в new оболочке. Также проверьте этот ответ, например,

: https://superuser.com/a/894748/432100

Похожие вопросы

6
10
11
5
16