Ответы:
Поиск сценария будет запускать команды в текущем процессе оболочки.
Выполнение скрипта запустит команды в новом процессе оболочки.
Используйте исходный код, если вы хотите, чтобы скрипт изменил среду в текущей запущенной оболочке. используйте выполнить иначе.
Если вы все еще не уверены, читайте дальше.
Чтобы прояснить некоторую путаницу в отношении синтаксиса для выполнения и синтаксиса для источника:
./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
не установлена и рабочий каталог не изменился.
Выходные данные скрипта ясно показывают, что переменная была установлена, а каталог был изменен. Проверка позже показывает, что переменная не установлена и каталог не изменен. Что случилось? Изменения были сделаны в новой оболочке. Текущая оболочка породила новую оболочку для запуска сценария. Сценарий выполняется в новой оболочке, и все изменения в среде вступают в силу в новой оболочке. После выполнения скрипта новая оболочка уничтожается. Все изменения среды в новой оболочке уничтожаются новой оболочкой. Только текущий текст выводится в текущей оболочке.
Теперь мы поставляем файл:
$ 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 установлена, и рабочий каталог изменился.
Sourcing скрипт не создает новую оболочку. Все команды выполняются в текущей оболочке, а изменения в среде вступают в силу в текущей оболочке.
Обратите внимание, что в этом простом примере результат выполнения аналогичен поиску сценария. Это не всегда так.
Рассмотрим следующий скрипт 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 остается прежним.
Как поиск, так и выполнение скрипта будут запускать команды в скрипте построчно, как если бы вы вводили эти команды вручную построчно.
Различия:
Используйте исходный код, если вы хотите, чтобы скрипт изменил среду в текущей запущенной оболочке. используйте выполнить иначе.
Смотрите также:
source myscript.sh
и . myscript.sh
?
Выполнение сценария запускает его в отдельном дочернем процессе, т. Е. Для обработки сценария вызывается отдельный экземпляр оболочки. Это означает, что любые переменные среды и т. Д., Определенные в сценарии, не могут быть обновлены в родительской (текущей) оболочке.
Выбор сценария означает, что он анализируется и выполняется самой текущей оболочкой. Это как если бы вы набрали содержимое скрипта. По этой причине исходный скрипт не обязательно должен быть исполняемым. Но он должен быть исполняемым, если вы выполняете его, конечно.
Если у вас есть позиционные аргументы в текущей оболочке, они неизменны.
Так что, если у меня есть файл, a.sh
содержащий:
echo a $*
и я делаю:
$ set `date`
$ source ./a.sh
Я получаю что-то вроде:
a Fri Dec 11 07:34:17 PST 2009
В то время как:
$ set `date`
$ ./a.sh
дает мне:
a
Надеюсь, это поможет.
sourcing - это то же самое, что вводить каждую строку скрипта в командной строке по одному ...
Выполнение запускает новый процесс, а затем запускает каждую строку сценария, изменяя только текущее окружение тем, что оно возвращает.
В дополнение к вышесказанному, выполнение сценария, как ./myscript
требуется, требует разрешения на выполнение для файла myscript, в то время как поиск не требует разрешения на выполнение. Вот почему chmod +x myscript
не требуется раньшеsource myscript
bash myscript
.
В источнике вы получите все дополнительные переменные, определенные в скрипте.
Поэтому, если у вас есть конфиги или определения функций, вы должны исходить, а не выполняться. Казни не зависят от родительской среды.
Если я правильно помню, выполнение сценария запускает исполняемый файл в #!
строке с файлом сценария в качестве аргумента (как правило, запускает новую оболочку и эффективно использует сценарий в новой оболочке, как в случае с #!/bin/sh
);
тогда как поиск сценария выполняет каждую строку в текущей среде оболочки, что полезно для изменения текущей оболочки (например, предоставления способа определения функций оболочки и экспорта переменных среды).
source
Команда выполняет предоставленный сценарий (разрешение на выполнение не является обязательным ) в текущей среде оболочки, а запускает./
предоставленный исполняемый сценарий в новой оболочке.
Также, проверьте этот ответ, например: https://superuser.com/a/894748/432100