Sự khác biệt giữa việc chạy tập lệnh bash script.sh và và.


42

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:


56

Đố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.shyêu cầu thực thi và các bit có thể đọc được, trong khi bash script.shchỉ 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/bashvà truyền ./script.sh dưới dạng đối số dòng lệnh.

  • bash script.shlàm cho shell của bạn chạy bashvà vượt qua script.shnhư là đối số dòng lệnh

Vì 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). bashQuá trình được tạo sau đó sẽ diễn giải script.shbởi vì nó được truyền dưới dạng đối số dòng lệnh. Bởi vì script.shchỉ được đọc bởi bashmột tệp thông thường, nên bit thực thi là không bắt buộc.


./script.shTuy 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.


3
Nếu bit thực thi không được đặt, bạn cũng có thể chạy tập lệnh bằng cách thực hiện "./script.sh"
Thế giới chó ăn thịt mèo

1
@Dog Bạn đúng rồi. Dấu chấm là một lối tắt cho lệnh 'nguồn' tích hợp, chạy tập lệnh trong quy trình bash hiện tại. Vì vậy, chỉ có bit có thể đọc được là bắt buộc.
SkyDan

5
@Dogeatcatworld trong khi đó là sự thật, chạy . ./script.shkhô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.
casey

12
Coi chừng việc tìm nguồn cung cấp một tập lệnh có thể dẫn đến ô nhiễm phiên tương tác. Ví dụ: nếu tập lệnh thay đổi biến môi trường PATH, thay đổi này sẽ ảnh hưởng đến các lệnh chạy theo nguồn. Cách tiếp cận này thực sự nên được dành riêng cho các tình huống mà bạn phụ thuộc vào các tác dụng phụ (tập lệnh thiết lập môi trường và tương tự). Đối với các tình huống khác khi bạn không thể thay đổi quyền, chạy lệnh trong dòng shebang, theo sau là tên tập lệnh là cách tiếp cận an toàn nhất.
ctt

6
Lưu ý rằng, nếu bạn lấy một tập lệnh trong thư mục hiện tại, bạn không cần sử dụng ./ ; chỉ nói . 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 exitcá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).
Scott

18

bash script.shgọ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.shbạ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.shkhả năng thực hiện nó trực tiếp thông qua ./script.sh.


2
Chà, không có gì khác biệt khi cho rằng đó /bin/bashlà lần đầu tiên bashtrong bạn $PATH.
cjm

Bạn đúng. Và shebang #!/bin/bashchỉ hoạt động nếu có/bin/bash
xx4h

Bash (phiên bản 4.2.37) trên hệ thống của tôi thực thi các tập lệnh ngay cả khi không cài đặt bit thực thi. Tại sao bạn nói bit thực thi là bắt buộc?
SkyDan

Có, bit thực thi chỉ cần bằng cách gọi qua ./script.sh.
xx4h

4

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.shbạ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.shbạn sẽ thấy không có gì được lặp lại, trong khi Delete_Self.shchính tập tin đã biến mất.

Vì vậy, sự khác biệt là:

  • bash script.shsẽ bỏ qua #! dòng, vì bash được chỉ định là chương trình để chạy script.sh.
  • ./script.shsẽ đọc #! dòng để xác định chương trình để chạy script.sh.

+1 cho ví dụ hay
ThisaruG

1

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 sourcemà bạn có thể gặp là .nội dung, nghĩa là

. activate my_env
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.