Câu trả lời:
Tìm kiếm một tập lệnh sẽ chạy các lệnh trong quy trình shell hiện tại .
Thực thi một tập lệnh sẽ chạy các lệnh trong một quy trình shell mới .
Sử dụng nguồn nếu bạn muốn tập lệnh thay đổi môi trường trong trình bao hiện đang chạy của bạn. sử dụng thực thi khác.
Nếu bạn vẫn còn bối rối, xin vui lòng đọc tiếp.
Để làm rõ một số nhầm lẫn phổ biến về cú pháp thực thi và cú pháp nguồn:
./myscript
Điều này sẽ thực thi myscript
với điều kiện là tệp có thể thực thi được và nằm trong thư mục hiện tại. Dấu chấm và dấu gạch chéo ( ./
) hàng đầu biểu thị thư mục hiện tại. Điều này là cần thiết bởi vì thư mục hiện tại thường không (và thường không nên) trong $PATH
.
myscript
Điều này sẽ thực thi myscript
nếu tập tin được thực thi và nằm trong một số thư mục trong $PATH
.
source myscript
Điều này sẽ nguồn myscript
. Các tập tin không cần phải được thực thi nhưng nó phải là một tập lệnh shell hợp lệ. Các tập tin có thể trong thư mục hiện tại hoặc trong một thư mục trong $PATH
.
. myscript
Điều này cũng sẽ nguồn myscript
. "Chính tả" này là chính thức theo định nghĩa của POSIX . Bash định nghĩa source
như một bí danh cho dấu chấm.
Xem xét myscript.sh
với nội dung sau:
#!/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
Trước khi chúng tôi thực thi tập lệnh trước tiên, chúng tôi kiểm tra môi trường hiện tại:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Biến FOO
không được xác định và chúng tôi đang ở trong thư mục chính.
Bây giờ chúng tôi thực hiện các tập tin:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Kiểm tra lại môi trường:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Biến FOO
không được đặt và thư mục làm việc không thay đổi.
Đầu ra tập lệnh cho thấy rõ ràng rằng biến đã được đặt và thư mục đã được thay đổi. Việc kiểm tra sau đó cho thấy biến không được đặt và thư mục không thay đổi. Chuyện gì đã xảy ra? Những thay đổi đã được thực hiện trong một vỏ mới . Các hiện vỏ sinh ra một mới shell để chạy các kịch bản. Kịch bản đang chạy trong trình bao mới và tất cả các thay đổi đối với môi trường có hiệu lực trong trình bao mới. Sau khi kịch bản được thực hiện, shell mới bị phá hủy. Tất cả các thay đổi đối với môi trường trong lớp vỏ mới đều bị phá hủy bằng lớp vỏ mới. Chỉ văn bản đầu ra được in trong vỏ hiện tại.
Bây giờ chúng tôi nguồn tập tin:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Kiểm tra lại môi trường:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
Biến FOO được đặt và thư mục làm việc đã thay đổi.
Tìm nguồn cung cấp kịch bản không tạo ra một vỏ mới. Tất cả các lệnh được chạy trong shell hiện tại và các thay đổi đối với môi trường có hiệu lực trong shell hiện tại.
Lưu ý rằng trong ví dụ đơn giản này, đầu ra của việc thực thi giống như tìm nguồn cung cấp tập lệnh. Điều này không nhất thiết phải luôn luôn như vậy.
Xem xét kịch bản sau đây pid.sh
:
#!/bin/sh
echo $$
(biến đặc biệt $$
mở rộng tới PID của quy trình shell đang chạy hiện tại)
Đầu tiên in PID của shell hiện tại:
$ echo $$
25009
Nguồn kịch bản:
$ source pid.sh
25009
Thực thi tập lệnh, lưu ý PID:
$ ./pid.sh
25011
Nguồn lại:
$ source pid.sh
25009
Thực hiện lại:
$ ./pid.sh
25013
Bạn có thể thấy rằng việc tìm nguồn cung cấp tập lệnh chạy trong cùng một quy trình trong khi thực thi tập lệnh sẽ tạo ra một quy trình mới mọi lúc. Quá trình mới đó là trình bao mới được tạo để thực thi tập lệnh. Tìm nguồn cung cấp kịch bản không tạo ra một vỏ mới và do đó, PID vẫn giữ nguyên.
Cả việc tìm nguồn cung ứng và thực thi tập lệnh sẽ chạy các lệnh trong dòng kịch bản theo từng dòng, như thể bạn đã gõ các lệnh đó theo từng dòng một.
Sự khác biệt là:
Sử dụng nguồn nếu bạn muốn tập lệnh thay đổi môi trường trong trình bao hiện đang chạy của bạn. sử dụng thực thi khác.
Xem thêm:
source myscript.sh
và . myscript.sh
?
Thực thi một tập lệnh chạy nó trong một tiến trình con riêng biệt, tức là, một thể hiện riêng biệt của shell được gọi để xử lý tập lệnh. Điều này có nghĩa là bất kỳ biến môi trường nào, v.v., được xác định trong tập lệnh không thể được cập nhật trong trình bao (hiện tại).
Tìm kiếm một tập lệnh có nghĩa là nó được phân tích cú pháp và được thực thi bởi chính trình bao hiện tại. Như thể bạn đã gõ nội dung của tập lệnh. Vì lý do này, kịch bản có nguồn gốc không cần phải được thực thi. Nhưng nó phải được thực thi nếu bạn đang thực hiện nó.
Nếu bạn có đối số vị trí trong trình bao hiện tại, chúng không thay đổi.
Vì vậy, nếu tôi có một tập tin a.sh
chứa:
echo a $*
và tôi làm:
$ set `date`
$ source ./a.sh
Tôi nhận được một cái gì đó như:
a Fri Dec 11 07:34:17 PST 2009
Trong khi:
$ set `date`
$ ./a.sh
đưa cho tôi:
a
Mong rằng sẽ giúp.
tìm nguồn cung ứng về cơ bản giống như nhập từng dòng của tập lệnh tại dấu nhắc lệnh một lần ...
Thực thi bắt đầu một quy trình mới và sau đó chạy từng dòng của tập lệnh, chỉ sửa đổi môi trường hiện tại bằng những gì nó trả về.
Ngoài ra, việc thực thi tập lệnh theo ./myscript
yêu cầu quyền thực thi đối với tệp myscript trong khi tìm nguồn cung cấp không yêu cầu bất kỳ quyền thực thi nào. Đó là lý do tại sao chmod +x myscript
không bắt buộc trướcsource myscript
bash myscript
.
Tìm nguồn cung ứng bạn nhận được tất cả các biến bổ sung được xác định trong tập lệnh.
Vì vậy, nếu bạn có cấu hình hoặc định nghĩa hàm, bạn nên nguồn và không thực thi. Thi hành độc lập với môi trường cha mẹ.
Nếu tôi nhớ lại chính xác, việc thực thi tập lệnh sẽ chạy tệp thực thi trong #!
dòng với tệp tập lệnh dưới dạng đối số (thường bắt đầu một trình bao mới và tìm nguồn cung cấp tập lệnh vào trình bao mới một cách hiệu quả, như với #!/bin/sh
);
trong khi đó, tìm nguồn cung cấp tập lệnh thực thi từng dòng trong môi trường shell hiện tại của bạn, rất hữu ích để thay đổi shell hiện tại của bạn (ví dụ: cung cấp một cách để xác định các hàm shell và xuất các biến môi trường).
source
lệnh thực thi tập lệnh được cung cấp (quyền thực thi là không bắt buộc ) trong môi trường shell hiện tại , trong khi ./
thực thi tập lệnh thực thi được cung cấp trong trình bao mới .
Ngoài ra, hãy kiểm tra câu trả lời này ví dụ: https://superuser.com/a/894748/432100