Вопрос: В чем разница между выполнением сценария Bash и его использованием?


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

A
> ./myscript

B
> source myscript

213
2017-12-11 15:24


Источник




Ответы:


Короткий ответ: sourcing будет запускать команды в текущем процессе оболочки. выполнение будет запускать команды в новом процессе оболочки. все еще запутался? то, пожалуйста, продолжайте читать длинный ответ.

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

Чтобы прояснить некоторую общую путаницу в отношении синтаксиса для выполнения и синтаксиса источника:

./myscript

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

myscript

казнить  myscript если файл является исполняемым и находится в некотором каталоге в $PATH,

source myscript

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

. myscript

Источник  myscript, Этот синтаксис определяемый POSIX, Определен Bash 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 не задано, и рабочий каталог не изменился.

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

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

$ 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

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

Резюме

Оба источника и выполнение скрипта будут запускать команды в сценарии по очереди, как если бы вы вводили эти команды вручную по строкам.

Различия заключаются в следующем:

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

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


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


275
2017-08-16 21:58



Одно использование источника создает рудиментарную форму файла конфигурации для ваших скриптов. Вы начинаете с установки различных переменных по умолчанию, а затем источника в чем-то вроде myscript.conf, и этот сценарий с исходными текстами может иметь инструкции присваивания, которые переопределяют любые значения, которые вы хотите. Поскольку исходный сценарий не начинается с # / bin / bash, его не рекомендуется выполнять непосредственно. - LawrenceC
Таким образом, источник похож на запуск его в глобальной области, а выполнение создает новую локальную область. Можно ли это расширить до функции в скрипте? для выполнения функции (обычно) или для «источника»? - aliteralmind
вызов функции оболочки обычно ведет себя подобно источнику. вызов функции оболочки внутри подоболочки ведет себя так же, как выполнение. - lesmana
Существует ли разница между использованием source myscript.sh а также . myscript.sh? - Holloway
практически никакой разницы при использовании bash. источник - это псевдоним, который следует расставить в bash. - lesmana


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

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

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

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

echo a $*

и я делаю:

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

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

a Fri Dec 11 07:34:17 PST 2009

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

$ set `date`
$ ./a.sh

дает мне:

a

Надеюсь, это поможет.


21
2017-12-11 15:35



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


sourcing по сути то же самое, что вводить каждую строку скрипта в командной строке по одному за раз ...

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


5
2017-12-11 15:27





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


4
2017-12-11 15:25





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


4
2018-02-23 07:27



Правда, но если это проблема, вы всегда можете запустить bash myscript, - Daniel Beck♦


Если я правильно помню, выполнение сценария запускает исполняемый файл в #! строка с файлом сценария в качестве аргумента (как правило, запускает новую оболочку и эффективно использует сценарий в новой оболочке, как в случае с #!/bin/sh);
в то время как поиск сценария выполняет каждую строку в текущей среде оболочки, что полезно для изменения текущей оболочки (например, предоставление способа определения функций оболочки и переменных внешней среды экспорта).


3
2017-12-11 15:27





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

Кроме того, проверьте этот ответ, например: https://superuser.com/a/894748/432100


2
2018-03-27 14:04