Nếu script.sh chỉ là một cái gì đó điển hình như
#!/bin/bash
echo "Hello World!"
Có một cách ưa thích để chạy tập lệnh? Tôi nghĩ rằng trước tiên bạn phải chmod nó để nó trở thành thực thi?
Nếu script.sh chỉ là một cái gì đó điển hình như
#!/bin/bash
echo "Hello World!"
Có một cách ưa thích để chạy tập lệnh? Tôi nghĩ rằng trước tiên bạn phải chmod nó để nó trở thành thực thi?
Câu trả lời:
Đối với tập lệnh cụ thể của bạn, một trong hai cách sẽ hoạt động, ngoại trừ ./script.sh
yêu cầu thực thi và các bit có thể đọc được, trong khi bash script.sh
chỉ yêu cầu bit có thể đọc được.
Lý do của sự khác biệt về yêu cầu quyền nằm ở cách chương trình diễn giải tập lệnh của bạn được tải:
./script.sh
làm cho trình bao của bạn chạy tệp như thể nó là một tệp thực thi thông thường.Shell tự rèn và sử dụng lệnh gọi hệ thống (ví dụ execve
) để làm cho hệ điều hành thực thi tệp trong quy trình rẽ nhánh. Hệ điều hành sẽ kiểm tra các quyền của tệp (do đó cần phải thực hiện bit thực thi) và chuyển tiếp yêu cầu đến trình tải chương trình , xem xét tệp và xác định cách thực hiện. Trong Linux, các tệp thực thi được biên dịch bắt đầu bằng số ma thuật ELF , trong khi các tập lệnh bắt đầu bằng #!
( hashbang ). Tiêu đề hashbang có nghĩa là tệp là một tập lệnh và cần được giải thích bởi chương trình được chỉ định sau hàm băm. Điều này cho phép chính tập lệnh cho hệ thống biết cách diễn giải tập lệnh.
Với tập lệnh của bạn, trình tải chương trình sẽ thực thi /bin/bash
và truyền ./script.sh
dưới dạng đối số dòng lệnh.
bash script.sh
làm cho shell của bạn chạy bash
và vượt qua script.sh
như là đối số dòng lệnhVì vậy, hệ điều hành sẽ tải bash
(thậm chí không nhìn vào script.sh
, vì đó chỉ là đối số dòng lệnh). bash
Quá trình được tạo sau đó sẽ diễn giải script.sh
bởi vì nó được truyền dưới dạng đối số dòng lệnh. Bởi vì script.sh
chỉ được đọc bởi bash
một tệp thông thường, nên bit thực thi là không bắt buộc.
./script.sh
Tuy nhiên, tôi khuyên bạn nên sử dụng vì bạn có thể không biết trình thông dịch nào đang yêu cầu. Vì vậy, hãy để trình tải chương trình xác định điều đó cho bạn.
. ./script.sh
không giống với bash script.sh
(hoặc ./script.sh
. Hãy xem xét tập lệnh #!/usr/bin/python -V
<newline> print test
.
. script.sh
. Nhưng tôi đồng ý với những người không khuyến khích sử dụng .
lệnh trên các tập lệnh không có nghĩa được gọi theo cách đó. Tôi ngạc nhiên khi không ai đề cập rằng, nếu tập lệnh chứa exit
các lệnh và bạn lấy nó, nó có thể đăng xuất bạn. Một vấn đề ít nghiêm trọng hơn sẽ là nếu tập lệnh thực hiện một cd
, vì điều đó cũng sẽ ảnh hưởng đến lớp vỏ (tương tác).
bash script.sh
gọi kịch bản trực tiếp bằng cách sử dụng bash.
./script.sh
đang sử dụng shebang #!/bin/bash
để xác định cách thực hiện.
Nếu bạn thực sự muốn biết, nhị phân nào được thực thi nếu bạn thực hiện, bash script.sh
bạn có thể tìm ra which bash
.
Vì vậy, trong ví dụ của bạn, nó không có sự khác biệt. Có, bạn phải có chmod +x script.sh
khả năng thực hiện nó trực tiếp thông qua ./script.sh
.
/bin/bash
là lần đầu tiên bash
trong bạn $PATH
.
#!/bin/bash
chỉ hoạt động nếu có/bin/bash
./script.sh
.
Tạo một tệp Delete_Self.sh như thế này:
#!/bin/rm
echo I am still here!
Chạy kịch bản này vì sh Delete_Self.sh
bạn sẽ thấy "Tôi vẫn ở đây!" vang vọng trở lại.
Làm cho nó có thể thực thi được và chạy nó vì ./Delete_Self.sh
bạn sẽ thấy không có gì được lặp lại, trong khi Delete_Self.sh
chính tập tin đã biến mất.
Vì vậy, sự khác biệt là:
bash script.sh
sẽ bỏ qua #! dòng, vì bash được chỉ định là chương trình để chạy script.sh../script.sh
sẽ đọc #! dòng để xác định chương trình để chạy script.sh
.Ngoài các câu trả lời khác, việc biết sự khác biệt giữa chạy tập lệnh qua ./script.sh
(i) và nguồn ./script.sh
(ii) là hữu ích - Phiên bản (i) tạo ra một vỏ mới để chạy lệnh, trong khi (ii) chạy nó trong shell hiện tại - có thể là bắt buộc nếu thực thi thay đổi các biến môi trường cần được bảo tồn sau khi thoát thực thi. Ví dụ, để kích hoạt môi trường conda python, phải sử dụng như sau:
source activate my_env
NB Một cách khác source
mà bạn có thể gặp là .
nội dung, nghĩa là
. activate my_env