Яка різниця між джерелом пошуку ('.' Або 'source') та виконанням файлу в bash?


76

Яка різниця між виконанням такого сценарію:

./test.sh

та виконання такого сценарію:

. test.sh?

Я спробував простий, дворядковий сценарій, щоб побачити, чи зможу я знайти, чи є різниця:

#!/bin/bash
ls

Але обидва . test.shі ./test.shповернули ту саму інформацію.


Вибачте, якщо це дублікат - при подальшому дослідженні я знайшов кілька сторінок з відповідною інформацією, шукаючи 'bash dot' замість 'bash'.
Натан

3
Так само, як test.shне те саме, що ./test.sh(перший викликає PATHпошук), так . test.shі . ./test.shвідрізняються однаково (колишній викликає PATHпошук). Здається, багато снарядів неявно включаються .в кінці PATHпід час .пошуку шляху, але така поведінка не є стандартною. Таким чином, більш точно порівняти test.shпроти . test.shі ./test.shпроти . ./test.sh.
jw013

Відповіді:


83

./test.shпрацює test.shяк окрема програма. Якщо файл test.shпочинається з файлу, це може бути сценарій bash #!/bin/bash. Але це може бути щось інше взагалі.

. ./test.shвиконує код файлу test.shвсередині запущеного екземпляра bash. Це працює так, ніби файл вмісту test.shбув включений текстуально замість . ./test.shрядка. (Майже: є кілька деталей, які відрізняються, такі як значення $BASH_LINENOта поведінка returnвбудованого.)

source ./test.shідентичний . ./test.shбашу (в інших оболонках sourceможе дещо відрізнятися або взагалі не існувати; .для включення в стандарт POSIX).

Найбільш часто помітна відмінність запуску окремого сценарію з ./test.shвключенням сценарію з .вбудованим в тому, що якщо test.shсценарій встановлює деякі змінні середовища, з окремим процесом встановлюється лише середовище дочірнього процесу, тоді як при включенні сценарію - середовище встановлено процес оболонки підошви. Якщо ви додасте рядок foo=barв test.shі echo $fooв кінці сценарію виклику, ви побачите різницю:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar

17
Також додавання echo $$до сценарію покаже різницю досить зрозумілою. $$Мінлива містить PID поточної оболонки.

1
Інший сценарій використання - це використання . ./test.shдзвінка з іншого сценарію оболонки для використання функцій, описаних у test.sh. Я маю на увазі, що не тільки змінні ви можете встановити, ви також можете створювати нові функції таким чином, які потім можна викликати з bash або якогось іншого сценарію. . /usr/libexec/company/tools; custom_command "variable"
Rqomey

9

Запуск сценарію перший спосіб запускає його як дочірній процес. Sourcing (другий спосіб), з іншого боку, запускає скрипт так, ніби ви ввели всі його команди в поточну оболонку - якщо сценарій встановить змінну, вона залишиться встановленою, якщо сценарій завершиться, ваш сеанс закінчиться. Дивіться help .документацію.


3

Ще одна річ, яку я зазначу, це те, що якщо у вас є такий псевдонім:

# add into .bashrc_aliases
alias ls='ls -lht'

Завдяки цьому ./test.shви отримаєте нормальний lsвихід (і інший PID, ніж поточна оболонка):

auraham@pandora:~/iso$ ./test.sh 
dsl-4.4.10.iso  test.sh
3136 # PID

За допомогою . test.shабо . ./test.shви отримаєте більш детальний вихід (і той самий PID, що і поточна оболонка):

auraham@pandora:~/iso$ echo $$
2767 # shell PID

auraham@pandora:~/iso$ . test.sh 
total 50M
drwxrwxr-x  2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x  1 auraham auraham   32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r--  1 auraham auraham  50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID

Ви можете включити це в .bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi Потім, ввести псевдоніми .bash_aliases.
аурахам

Звичайно, але хіба вам ще не потрібно використовувати aliasключове слово? (Можливо, це просто помилка у твоєму дописі - на лінії 3?)
Емануель Берг

абсолютно правильно, моя помилка. Дякуємо @EmanuelBerg
auraham

-1

Основне використання для мене source(або .) - це функції bash .

У мене є сценарії з багатьма функціями, і всі вони виконую своїми .bashrc. Функції "стають" командами, якими я часто користуюся.


Я спробував усі три методи у .bashrc - джерело, абсолютне положення сценарію та ім'я команди (розміщення сценарію в папці PATH) - і всі три методи спрацювали.
Емануель Берг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.