Sự khác biệt giữa tìm nguồn cung ứng ('.' Hoặc 'nguồn') và thực thi một tệp trong bash là gì?


76

Sự khác biệt giữa thực thi một tập lệnh như thế này là gì:

./test.sh

và thực thi một kịch bản như thế này:

. test.sh?

Tôi đã thử một kịch bản hai dòng đơn giản để xem liệu tôi có thể tìm thấy nếu có sự khác biệt không:

#!/bin/bash
ls

Nhưng cả hai . test.sh./test.shtrả lại cùng một thông tin.


Xin lỗi nếu đây là một bản sao - khi điều tra thêm, tôi đã tìm thấy một số trang có thông tin liên quan bằng cách tìm kiếm 'bash dot' thay vì 'bash.'.
Natan

3
Cũng giống như test.shkhông giống như ./test.sh(lần đầu tiên gọi một PATHtìm kiếm), vì vậy . test.sh. ./test.shkhác nhau theo cùng một cách (trước đây gọi một PATHtìm kiếm). Nhiều shell dường như hoàn toàn bao gồm .vào cuối PATHkhi thực hiện .tìm kiếm đường dẫn, nhưng hành vi này không chuẩn. Vì vậy, nó là chính xác hơn để so sánh test.shvs . test.sh./test.shvs . ./test.sh.
jw013

Câu trả lời:


83

./test.shchạy test.shnhư một chương trình riêng biệt. Nó có thể là một tập lệnh bash, nếu tập tin test.shbắt đầu bằng #!/bin/bash. Nhưng nó có thể là một cái gì đó khác hoàn toàn.

. ./test.shthực thi mã của tệp test.shbên trong phiên bản bash đang chạy. Nó hoạt động như thể tệp nội dung test.shđã được bao gồm bằng văn bản thay vì . ./test.shdòng. (Hầu hết: có một vài chi tiết khác nhau, chẳng hạn như giá trị $BASH_LINENOvà hành vi của returnnội dung.)

source ./test.shgiống hệt như . ./test.shtrong bash (trong các shell khác, sourcecó thể hơi khác hoặc không tồn tại hoàn toàn; .để đưa vào trong tiêu chuẩn POSIX).

Sự khác biệt thường thấy nhất giữa việc chạy một tập lệnh riêng biệt ./test.shvà bao gồm tập lệnh với phần .dựng sẵn là nếu test.shtập lệnh đặt một số biến môi trường, với một quy trình riêng biệt, chỉ có môi trường của quy trình con được đặt, trong khi với tập lệnh bao gồm, môi trường của quá trình vỏ duy nhất được thiết lập. Nếu bạn thêm một dòng foo=barvào test.shecho $fooở cuối tập lệnh gọi, bạn sẽ thấy sự khác biệt:

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

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

17
Ngoài ra thêm echo $$vào kịch bản sẽ cho thấy sự khác biệt khá rõ ràng. Các $$biến giữ PID của vỏ hiện hành.

1
Một kịch bản sử dụng khác là sử dụng . ./test.shcuộc gọi từ trong một tập lệnh shell khác để sử dụng các hàm được mô tả trong test.sh. Ý tôi là, nó không chỉ là các biến mà bạn có thể đặt, bạn cũng có thể tạo các hàm mới theo cách này có thể gọi được từ bash hoặc một số tập lệnh khác. . /usr/libexec/company/tools; custom_command "variable"
Rqomey

9

Chạy một kịch bản theo cách đầu tiên chạy nó như một tiến trình con. Tìm nguồn (cách thứ hai), mặt khác, chạy tập lệnh như thể bạn đã nhập tất cả các lệnh của nó vào trình bao hiện tại - nếu tập lệnh đặt một biến, nó sẽ vẫn được đặt, nếu tập lệnh thoát, phiên của bạn sẽ thoát. Xem help .tài liệu.


3

Một điều khác mà tôi lưu ý là nếu bạn có một bí danh như thế này:

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

Với ./test.shbạn sẽ nhận được một lsđầu ra bình thường (và một PID khác với shell hiện tại):

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

Với . test.shhoặc . ./test.shbạn sẽ nhận được một đầu ra chi tiết hơn (và cùng một PID so với vỏ hiện tại):

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

Bạn có thể đưa cái này vào .bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi Then, đặt bí danh của bạn vào .bash_aliases.
auraham

Tất nhiên, nhưng bạn vẫn không phải sử dụng aliastừ khóa? (Có lẽ đó chỉ là một lỗi trong bài đăng của bạn - trên dòng 3?)
Emanuel Berg

Hoàn toàn chính xác, sai lầm của tôi. Cảm ơn @EmanuelBerg
auraham

-1

Cách sử dụng chính đối với tôi đối với source(hoặc .) là các hàm bash .

Tôi có các kịch bản với nhiều chức năng và tôi thực hiện tất cả chúng với .bashrc. Các hàm "trở thành" các lệnh mà tôi thường sử dụng.


Tôi đã thử cả ba phương thức trong .bashrc - nguồn, vị trí tuyệt đối của tập lệnh và tên của lệnh (đặt tập lệnh trong thư mục PATH) - và cả ba phương thức đều hoạt động.
Emanuel Berg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.