Sự khác biệt giữa #! / Bin / sh và #! / Bin / bash là gì?


280

nếu tôi viết

#!/bin/bash
echo "foo"

hoặc là

#!/bin/sh
echo "foo"

cả hai sản lượng như nhau. Tôi đã thấy một số kịch bản bắt đầu bằng #!/bin/shhoặc #!/bin/bash. Có sự khác biệt nào giữa chúng không?

Câu trả lời:


242

bashshlà hai vỏ khác nhau. Về cơ bản bashsh, với nhiều tính năng hơn và cú pháp tốt hơn. Hầu hết các lệnh làm việc như nhau, nhưng chúng khác nhau.

Đã nói rằng, bạn nên nhận ra /bin/shtrên hầu hết các hệ thống sẽ là một liên kết tượng trưng và sẽ không gọi sh. Trong Ubuntu /bin/shđược sử dụng để liên kết đến bash, hành vi điển hình trên các bản phân phối Linux, nhưng giờ đã thay đổi thành liên kết với một trình bao khác gọi là dash . Tôi sẽ sử dụng bash, vì đó là khá nhiều tiêu chuẩn (hoặc ít nhất là phổ biến nhất, từ kinh nghiệm của tôi). Trong thực tế, các vấn đề phát sinh khi một tập lệnh bash sẽ sử dụng #!/bin/shbởi vì người tạo tập lệnh giả định liên kết là bashkhi nó không phải như vậy.

Để biết thêm thông tin, http://man.cx/sh , http://man.cx/bash .


24
Đoạn đầu tiên của bạn khá sai lệch. "sh" hoàn toàn không phải là một hệ vỏ, mà là một liên kết tượng trưng cho hệ thống hiện đang được cấu hình , mà trên các hệ thống Linux thường là bash hoặc dash (các phiên bản gần đây của Ubuntu sử dụng phiên bản sau).
thomasrutter

18
/bin/shđã từng là một vỏ được gọi là bourne shell vào năm 1977. bash là một vỏ tương thích / bin / sh có thể được sử dụng như là một thay thế vỏ bourne phù hợp với posix. vi.wikipedia.org/wiki/Bourne_shell
Alex

5
bash là một tiêu chuẩn thực tế (được sử dụng rất rộng rãi) nhưng nó không phải là "tiêu chuẩn"; sh trên Ubuntu sử dụng dash , đây là một vỏ tương thích Posix, vì vậy nó thực sự là tiêu chuẩn. Lời khuyên của tôi là sử dụng dấu gạch ngang thường xuyên nhất có thể cho tập lệnh, đặc biệt là cho tập lệnh phía máy chủ. Mặc dù bash có nhiều biểu cảm hơn, dash chạy nhanh hơn khá nhiều và an toàn hơn.
Rick-777

@ Rick-777 Vậy tôi có nên đặt #! / Bin / dash một cách rõ ràng ở đầu tập lệnh của mình không? Tôi cũng đã viết các tập lệnh trong đó tôi chỉ viết các lệnh và thực thi với ./scriptName và nó đã hoạt động tốt. Là #! / Bin / yourShellHere có cần thiết không?
dùng137717

@ Rick-777 Trong trường hợp tôi loại trừ bất kỳ #! / Bin / shellName nào, tôi đã đặt tên tệp là fileName.sh. Điều đó sẽ ngầm liên kết đến hệ thống ưa thích mà không cần khai báo #! / Bin / sh?
dùng137717

82

Trên Linux và các hệ thống tương tự Unix khác, bạn có nhiều lựa chọn về hệ vỏ.

Shell không chỉ chịu trách nhiệm vẽ lời nhắc nhỏ của bạn mà còn diễn giải các lệnh của bạn, đặc biệt nếu bạn đặt logic phức tạp như ống dẫn, điều kiện, v.v.

bash là shell phổ biến nhất được sử dụng làm shell mặc định cho người dùng hệ thống Linux. Nó là hậu duệ tinh thần của các hệ vỏ khác được sử dụng trong suốt lịch sử Unix. Tên của nó, bash là tên viết tắt của Bourne-Again Shell, một sự tôn kính đối với vỏ Bourne mà nó được thiết kế để thay thế, mặc dù nó cũng kết hợp các tính năng từ C Shell và Korn Shell.

Nó chạy, những ngày này, từ /bin/bash- bất kỳ hệ thống nào có bash sẽ có thể truy cập được ở đây.

Tuy nhiên, không chỉ người dùng sử dụng vỏ. Các kịch bản lệnh ( shell script ) cần shell để giải thích chúng. Khi bạn chạy tập lệnh shell, hệ thống của bạn cần khởi động quy trình shell để thực thi tập lệnh của bạn.

Vấn đề là, các shell khác nhau có sự mâu thuẫn nhỏ giữa chúng và khi nói đến việc chạy các script, đây có thể là một vấn đề thực sự. bash có khá nhiều tính năng kịch bản chỉ dành riêng cho bash và không có các shell khác. Điều này tốt, nếu bạn luôn sử dụng bash để chạy các tập lệnh đó. Các shell khác có thể cố gắng mô phỏng bash hoặc tuân thủ tiêu chuẩn POSIX, bash này hỗ trợ khá tốt (mặc dù có thêm các tiện ích mở rộng của riêng nó).

Có thể chỉ định ở đầu tập lệnh shell mà nó nên được chạy bằng cách sử dụng shebang. Một tập lệnh có thể chỉ định #!/bin/bashtrên dòng đầu tiên, có nghĩa là tập lệnh phải luôn được chạy bằng bash, chứ không phải là shell khác.

/ bin / sh là một tệp thực thi đại diện cho hệ thống shell . Trên thực tế, nó thường được thực hiện như một liên kết tượng trưng chỉ đến thực thi cho bất kỳ shell nào là shell hệ thống. Shell hệ thống là loại shell mặc định mà các script hệ thống nên sử dụng. Trong các bản phân phối Linux, trong một thời gian dài, đây thường là một liên kết tượng trưng cho bash , đến nỗi nó đã trở thành một quy ước để luôn liên kết / bin / sh với bash hoặc shell tương thích với bash. Tuy nhiên, trong vài năm qua, Debian (và Ubuntu) đã quyết định chuyển vỏ hệ thống từ bash sang dash- một lớp vỏ tương tự - phá vỡ truyền thống lâu đời trong Linux (tốt, GNU) về việc sử dụng bash cho / bin / sh. Dash được xem như một trình duyệt nhẹ hơn và nhanh hơn, có thể có lợi cho tốc độ khởi động (và những thứ khác đòi hỏi nhiều tập lệnh shell, như tập lệnh cài đặt gói).

Dash tương thích khá tốt với bash, dựa trên cùng tiêu chuẩn POSIX. Tuy nhiên, nó không thực hiện các phần mở rộng dành riêng cho bash. Có các tập lệnh tồn tại sử dụng #!/bin/sh(shell hệ thống) làm shebang của chúng, nhưng yêu cầu các phần mở rộng dành riêng cho bash. Đây hiện được coi là một lỗi cần được sửa bởi Debian và Ubuntu, những người yêu cầu / bin / sh để có thể hoạt động khi được chỉ ra dấu gạch ngang.

Mặc dù hệ thống của Ubuntu đang trỏ đến dấu gạch ngang, nhưng vỏ đăng nhập của bạn khi người dùng tiếp tục bị bash vào thời điểm này. Đó là, khi bạn đăng nhập vào một trình giả lập thiết bị đầu cuối ở bất cứ đâu trong Linux, vỏ đăng nhập của bạn sẽ bị bash. Tốc độ hoạt động không phải là vấn đề quá lớn khi shell được sử dụng tương tác và người dùng đã quen với bash (và có thể có các tùy chỉnh cụ thể của bash trong thư mục chính của họ).

Những gì bạn nên sử dụng khi viết kịch bản

Nếu tập lệnh của bạn yêu cầu các tính năng chỉ được hỗ trợ bởi bash, hãy sử dụng #!/bin/bash.

Nhưng nếu có thể, tốt nhất là đảm bảo tập lệnh của bạn tương thích với POSIX và việc sử dụng #!/bin/sh, luôn luôn, đáng tin cậy, chỉ vào vỏ hệ thống tương thích POSIX ưa thích trong mọi cài đặt.


18

Ngoài các câu trả lời trước đó, ngay cả khi /bin/shlà một liên kết tượng trưng đến /bin/bash, #!/bin/shkhông hoàn toàn tương đương với #!/bin/bash.

Từ trang bash (1) man :

"Nếu bash được gọi với tên sh, nó sẽ cố gắng bắt chước hành vi khởi động của các phiên bản lịch sử của sh càng gần càng tốt, đồng thời tuân thủ tiêu chuẩn POSIX."

Ví dụ cú pháp cụ thể của bash:

 exec  > >(tee logfile.txt)

đưa ra một lỗi trong một vỏ bắt đầu bằng #!/bin/sh, ngay cả với liên kết tượng trưng sh-> bash tại chỗ.


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.