Câu trả lời ngắn
Trong câu hỏi của bạn, lệnh thứ hai không sử dụng hàm .
dựng sẵn hay vỏ source
dựng. Thay vào đó, bạn thực sự đang chạy tập lệnh trong một shell riêng, bằng cách gọi nó theo tên như bạn làm với bất kỳ tệp thực thi nào khác. Điều này không cung cấp cho nó một tập hợp các biến riêng biệt (mặc dù nếu bạn xuất một biến trong vỏ cha của nó, nó sẽ là một biến môi trường cho bất kỳ tiến trình con nào , và do đó sẽ được bao gồm trong các biến của vỏ con ). Nếu bạn thay đổi /
thành một khoảng trắng, thì nó sẽ chạy nó với tích .
hợp sẵn, tương đương với source
.
Giải thích mở rộng
Đây là cú pháp của trình source
bao dựng sẵn, thực thi nội dung của tập lệnh trong trình bao hiện tại (và do đó với các biến của trình bao hiện tại):
source testenv.sh
Đây là cú pháp của tích .
hợp sẵn, thực hiện tương tự như source
:
. testenv.sh
Tuy nhiên, cú pháp này chạy tập lệnh dưới dạng tệp thực thi, khởi chạy shell mới để chạy nó:
./testenv.sh
Đó là không sử dụng tích .
hợp. Thay vào đó, .
là một phần của đường dẫn đến tệp bạn đang thực hiện. Nói chung, bạn có thể chạy bất kỳ tệp thực thi nào trong trình bao bằng cách gọi nó với tên chứa ít nhất một /
ký tự. Để chạy một tệp trong thư mục hiện tại, trước đó ./
là cách dễ nhất. Trừ khi thư mục hiện tại nằm trong bạn PATH
, bạn không thể chạy tập lệnh bằng lệnh testenv.sh
. Điều này là để ngăn mọi người vô tình thực thi các tệp trong thư mục hiện tại khi họ có ý định thực thi lệnh hệ thống hoặc một số tệp khác tồn tại trong một số thư mục được liệt kê trong PATH
biến môi trường.
Vì chạy tệp theo tên (chứ không phải với source
hoặc .
) chạy tệp trong trình bao mới, nên nó sẽ có tập hợp các biến shell riêng. Shell mới kế thừa các biến môi trường từ quá trình gọi (trong trường hợp này là shell tương tác của bạn) và các biến môi trường đó trở thành biến shell trong shell mới. Tuy nhiên, để một biến shell được chuyển sang shell mới, một trong những điều sau đây phải là trường hợp:
Biến shell đã được xuất, làm cho nó trở thành biến môi trường. Sử dụng export
vỏ tích hợp cho việc này. Trong ví dụ của bạn, bạn có thể sử dụng export MY_VAR=12345
để đặt và xuất biến trong một bước hoặc nếu nó đã được đặt, bạn chỉ cần sử dụng export MY_VAR
.
Biến shell được đặt rõ ràng và được truyền cho lệnh bạn đang chạy, khiến nó là biến môi trường trong suốt thời gian của lệnh đang được chạy. Điều này thường hoàn thành rằng:
MY_VAR=12345 ./testenv.sh
Nếu MY_VAR
là một biến shell chưa được xuất, bạn thậm chí có thể chạy testenv.sh
với MY_VAR
biến như một biến môi trường bằng cách đặt nó vào chính nó :
MY_VAR="$MY_VAR" ./testenv.sh
./
Cú pháp cho tập lệnh Yêu cầu một dòng Hashbang hoạt động (Chính xác)
Nhân tiện, xin lưu ý rằng, khi bạn gọi một tệp thực thi bằng tên như trên (chứ không phải với phần tử tích hợp .
hoặc source
shell), chương trình shell nào được sử dụng để chạy nó thường không được xác định bởi shell nào bạn đang chạy nó . Thay thế:
Đối với các tệp nhị phân, kernel có thể được cấu hình để chạy các tệp thuộc loại cụ thể đó. Nó kiểm tra hai byte đầu tiên của tệp để tìm "số ma thuật" cho biết loại thực thi nhị phân đó là gì. Đây là cách nhị phân thực thi có thể chạy.
Tất nhiên, điều này là vô cùng quan trọng, bởi vì một tập lệnh không thể chạy mà không có trình bao hoặc trình thông dịch khác, đây là một tệp nhị phân thực thi! Thêm vào đó, nhiều lệnh và ứng dụng được biên dịch nhị phân chứ không phải tập lệnh.
( #!
là biểu diễn văn bản của "số ma thuật" biểu thị một văn bản thực thi.)
Đối với các tệp được cho là chạy trong trình bao hoặc ngôn ngữ được dịch khác, dòng đầu tiên trông như sau:
#!/bin/sh
/bin/sh
có thể được thay thế bằng bất kỳ trình bao hoặc trình thông dịch nào khác nhằm chạy chương trình. Ví dụ: chương trình Python có thể bắt đầu bằng dòng:
#!/usr/bin/python
Những dòng này được gọi là hashbang, shebang và một số tên tương tự khác. Xem mục FOLDOC này , bài viết Wikipedia này và #! / Bin / sh được người phiên dịch đọc? để biết thêm thông tin.
Nếu một tệp văn bản được đánh dấu thực thi và bạn chạy nó từ shell của bạn (như ./filename
) nhưng nó không bắt đầu bằng #!
, kernel không thực thi được. Tuy nhiên, thấy rằng điều này đã xảy ra, shell của bạn sẽ cố gắng chạy nó bằng cách chuyển tên của nó cho một số shell. Có vài yêu cầu đặt trên những gì shell đó là ( "vỏ trách nhiệm thực thi một lệnh tương đương với việc có một vỏ gọi ..." ). Trong thực tế , một số shell - bao gồm bash
* - vượt qua một thể hiện khác của chúng, trong khi một số khác sử dụng/bin/sh
. Tôi đặc biệt khuyên bạn nên tránh điều này và sử dụng một dòng hashbang thay vào đó (hoặc chạy tập lệnh bằng cách chuyển nó đến trình thông dịch mong muốn, ví dụ bash filename
:).
* Hướng dẫn sử dụng GNU Bash , 3.7.2 Tìm kiếm và thực thi lệnh : "Nếu việc thực thi này thất bại vì tệp không ở định dạng thực thi và tệp không phải là một thư mục, nó được coi là một tập lệnh shell và shell thực thi nó như được mô tả trong Shell Script . "
source
là các chức năng đã có sẵn từ bash mà không cần phải tải hoặc khởi chạy lại. Ví dụ#!/bin/bash function olakease {echo olakease;}
. Khi bạn tải nó vớisource file.sh
bạn có thể gọi trực tiếpolakease
từ bash. Tôi thực sự thích điều đó. Nguồn thực thi sau đó tải rất nhiều thứ, dấu chấm.
chỉ để thực hiện và là một cái gì đó giống như sử dụngbash file.sh