Відповіді:
Sourcing скрипт буде запускати команди в поточному процесі оболонки.
Виконання сценарію запустить команди в новому процесі оболонки.
Використовуйте джерело, якщо ви хочете, щоб сценарій змінив оточення в поточній запущеній оболонці. використовувати Execute інакше.
Якщо ви все ще плутаєтеся, читайте далі.
Щоб уточнити загальну плутанину щодо синтаксису для виконання та синтаксису до джерела:
./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
не встановлена, а робочий каталог не змінювався.
Вихід сценарію чітко показує, що змінна була встановлена і каталог змінено. Після цього перевірка показує, що змінна не встановлена та каталог не змінений. Що трапилось? Зміни внесені в нову оболонку. Поточна оболонка породила нову оболонку для запуску сценарію. Сценарій працює в новій оболонці, і всі зміни в оточенні набувають чинності в новій оболонці. Після виконання сценарію нова оболонка знищується. Усі зміни середовища в новій оболонці знищуються з новою оболонкою. У поточній оболонці друкується лише вихідний текст.
Тепер ми джерело файлу:
$ 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 залишається таким же.
Як джерело, так і виконання сценарію будуть виконувати команди в скрипті по рядку, як якщо б ви ввели ці команди вручну, рядок.
Відмінності:
Використовуйте джерело, якщо ви хочете, щоб сценарій змінив оточення в поточній запущеній оболонці. використовувати Execute інакше.
Дивитися також:
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
Сподіваюся, що це допомагає.
пошук по суті такий же, як і введення кожного рядка сценарію в командному рядку по одному ...
Виконання запускає новий процес, а потім запускає кожен рядок сценарію, лише змінюючи поточне середовище тим, що він повертає.
На додаток до вище, виконання сценарію ./myscript
вимагає виконання дозволу на сценарій файлу, тоді як джерело не вимагає дозволу на виконання. Ось чому раніше chmod +x myscript
цього не потрібноsource myscript
bash myscript
.
За допомогою джерела ви отримуєте всі додаткові змінні, визначені в сценарії.
Отже, якщо у вас є конфігурації або визначення функцій, ви повинні джерело, а не виконання. Виконання не залежить від батьківського середовища.
Якщо я пам'ятаю правильно, виконання сценарію запускає виконуваний файл у #!
рядку із файлом сценарію як аргумент (як правило, запускається нова оболонка та ефективно передається сценарій у новий оболонку, як і у випадку #!/bin/sh
);
тоді як джерело скрипту виконує кожен рядок у вашому поточному середовищі оболонки, що корисно мутувати поточну оболонку (наприклад, надаючи спосіб визначення функцій оболонки та експорту змінних середовищ).
source
команда виконує наданий скрипт (дозвіл на виконання файлу не є обов'язковим ) у поточному середовищі оболонки, в той час як ./
виконується наданий виконуваний сценарій у новій оболонці.
Також перевірте, наприклад, цю відповідь: https://superuser.com/a/894748/432100