Có bất kỳ lý do để có một shebang chỉ vào / bin / sh chứ không phải / bin / bash không?


53

Trong hầu hết các kịch bản shell mà tôi đã xem (ngoài những kịch bản tôi chưa tự viết), tôi nhận thấy rằng shebang được đặt thành #!/bin/sh. Điều này không thực sự làm tôi ngạc nhiên về các kịch bản cũ hơn, nhưng nó cũng có trên các kịch bản khá mới.

Có bất kỳ lý do nào để thích /bin/shhơn không /bin/bash, vì bashkhá phổ biến và thường được mặc định, trên nhiều máy Linux và BSD sẽ hoạt động tốt trở lại sau một thập kỷ?


23
Đó là một phần tốt để sử dụng /bin/shnếu bạn không sử dụng các bashchức năng cụ thể . Một ngày nào đó bạn có thể phải sử dụng một trong các tập lệnh của mình trên một hệ thống chưa được cài đặt (máy chủ từ xa, máy tính nhúng ...)
Mathieu

1
nói chung, bạn nên tránh đặt câu hỏi cho vay để trả lời dựa trên ý kiến (đó là cách khả thi duy nhất tôi tin rằng câu hỏi này có thể được trả lời - nhưng đó chỉ là ý kiến của tôi ) .
mikeerv

9
Tôi tin rằng có thể trả lời câu hỏi này mà không liên quan đến ý kiến ​​đơn thuần, bằng cách chỉ ra ít nhất hai tổ chức đã giải quyết vấn đề này trong một số năm, và nhìn vào lịch sử và kết quả. Với rất nhiều đọc thêm kèm theo, để khởi động. ☺
JdeBP

3
@JulesMazur ...the answers so far are fairly subjective...Một tuyên bố "chủ quan" về cơ bản là dựa trên quan điểm theo định nghĩa. /bin/bashchỉ nên được sử dụng khi bash là cần thiết rõ ràng. Trong hơn 40 năm làm nhà phát triển, từ lâu bash, tôi gần như không bao giờ cần nó một cách rõ ràng trừ khi thử nghiệm. (Tôi cũng cố gắng tránh các tiện ích mở rộng hệ vỏ, nhưng hầu hết các tập lệnh của tôi đều nhằm phân phối.) Nhiều tập lệnh trên mạng cũng nên được sử dụng cho mục đích sử dụng rộng rãi.
user2338816

2
@ user2338816 xấu của tôi, ý tôi là khách quan . Cảm ơn điểm của bạn!
Jules

Câu trả lời:


83
  1. Có những hệ thống không vận chuyển bash theo mặc định (ví dụ FreeBSD).
  2. Ngay cả khi bash được cài đặt, nó có thể không được đặt trong /bin.
  3. Hầu hết các tập lệnh đơn giản không yêu cầu bash.
  4. Sử dụng trình bao POSIX dễ mang theo hơn và các tập lệnh sẽ chạy trên nhiều hệ thống khác nhau.

17
Một lý do khác: thường / bin / sh nhanh hơn bash, hoặc ít nhất là tải nhanh hơn (do nhỏ hơn).
derobert

5
@derobert, /bin/shlà nhanh hơn nếu nó không phải là bash, vẫn còn một vài hệ thống như OS / X hoặc RHEL nơi /bin/shbash.
Stéphane Chazelas

1
Không. Một số hệ điều hành liên kết nó, bởi vì bash tương thích ngược.
Sobrique

7
Khá nhiều kịch bản cho rằng đó /bin/sh/bin/bash. Ubuntu chuyển từ bash sang dash đã phá vỡ tất cả chúng.
atamanroman

19
@atamanroman: Các tập lệnh không chính xác ngay từ đầu, chúng nên được sử dụng #!/bin/bashnếu chúng muốn Bash (không có gì sai với điều đó!). Thay đổi chủ yếu được thực hiện ngược dòng trong Debian. Nó cải thiện trải nghiệm người dùng, nó có tác động có thể đo lường được về thời gian khởi động hệ thống. Nó cũng tác động tích cực đến an ninh, xem "Shellshock".
Dietrich Epp

28

Hầu hết các tập lệnh hệ thống trong (liên quan đến Debian: Ubuntu, Mint, v.v.) Linux được viết để chạy trong dấu gạch ngang nhanh hơn, đó là mặc định / bin / sh trong các hệ thống đó. Lý do có hai mặt:

  • Tốc độ của hệ thống. Một mã nhỏ hơn của dấu gạch ngang tải nhanh hơn và cũng chạy nhanh hơn. Với một số (nhỏ?) Nỗ lực bổ sung (chi phí) cho các lập trình viên của các kịch bản shell.

  • Bảo vệ. Có sự đa dạng của vỏ giúp khả năng phục hồi các lỗi. Các hệ thống Debian hầu như không dễ bị shellshock vì shell mặc định không có lỗ hổng như vậy.

Bash thực sự là vỏ mặc định cho người dùng , vì nó mạnh hơn và có nhiều yếu tố hơn để giúp mã hóa dễ dàng hơn. Nó cũng là mặc định shtrong Mac OS (một liên kết từ / bin / sh). Tuy nhiên, việc gọi bashvới tên liên kết shlàm cho nó bắt đầu như một vỏ tương thích posix.


2
Một bộ hạn chế hơn các công cụ có sẵn của một vỏ đơn giản hơn làm cho việc viết mã cho nó trở nên khó khăn hơn (xin vui lòng tránh bất kỳ cuộc chiến cuồng tín nào về việc này). Đó là lý do tại sao một số người dùng thích zsh, công cụ thậm chí còn có nhiều công cụ hơn bash. Tôi thích Bash hơn là sự cân bằng giữa cả hai thái cực.

4
@RobertL, nhiều phương tiện được thêm vào trong ksh và được thông qua bởi bash tồn tại bởi vì chúng dễ dàng thực hiện quá trình viết các tập lệnh mạnh mẽ và chính xác. Ví dụ, không có các bổ sung khác nhau cho phép thực hiện chuyển nhượng và đánh giá gián tiếp một cách an toàn, người ta có thể tìm thấy chính mình bằng cách sử dụng eval, với tiếp xúc bảo mật của người phục vụ; tương tự, không có hỗ trợ regex tích hợp, người ta có thể cần sử dụng các lệnh bên ngoài (ở mức phạt hiệu năng nặng) để khớp ngay cả trong một dòng, v.v.
Charles Duffy

1
@RuiFRibeiro, không có gì được liên kết tĩnh trong Debian. Dash bị hạn chế hơn, nhưng nó bị hạn chế chủ yếu ở các tính năng tương tác (không hoàn thành và như vậy) để nó nhanh hơn cho các tập lệnh.
Jan Hudec

21

Những người khác đã chỉ ra rằng các tiền đề của câu hỏi, rằng vỏ Bourne Again là mặc định và có mặt khắp nơi, là hoàn toàn sai.

Thêm vào đó, thực sự có những lý do chính đáng để sử dụng một cái gì đó ngoài shell Bourne Again để diễn giải các kịch bản shell. Những lý do thúc đẩy dự án lớn của Ubuntu và Debian, trong một số năm, để loại bỏ bashisms và để làm cho càng nhiều của các kịch bản shell chạy bởi hệ thống khởi tạo (mà là một rất nhiều của kịch bản shell với hệ thống 5 rc) và gói cài đặt / gỡ bỏ sử dụng các Vỏ Shell Almquist thay vì vỏ Bourne Again.

Nói một cách đơn giản: Shell Bourne Again, chứa đầy đủ các tính năng tương tác, không phải là trình thông dịch shell nhanh nhất cho tập lệnh shell tuân thủ POSIX. Vì vậy, nếu ai đó có thể tạo các tập lệnh shell của một người tuân thủ POSIX, diễn giải chúng bằng một chương trình nhẹ hơn, như trình vỏ Debian Almquist, hệ thống của một người sẽ hoạt động tốt hơn. (Cuối cùng, Debian phải điều chỉnh một chút cho hệ vỏ Almquist, để thêm hỗ trợ cho một vài cấu trúc vỏ không phải POSIX đơn giản là được nhúng quá sâu và rộng rãi và quá hữu dụng để loại bỏ.)

Kết quả của tất cả là một lợi ích lớn trong hiệu suất bootstrap.

Vì vậy, có hai lớp vỏ khác nhau để xem xét, ở đây:

  • Các shell với tất cả các tính năng tương tác hào nhoáng, được cấu hình là các shell đăng nhập tương tác cho người dùng trong cơ sở dữ liệu tài khoản.
  • Các shell giải thích rất nhiều script một cách nhanh chóng, được sử dụng làm trình thông dịch script bởi các chương trình shell script.

Lưu ý rằng nói về điều này là "thích /bin/sh" là quá đơn giản. Debian thực sự có ít nhất hai mục tiêu:

  1. Đối mặt với các quản trị viên sử dụng shell Debian Almquist, Z Shell (ở chế độ POSIX), shell Bourne Again (ở chế độ POSIX), shell MirBSD Korn và các loại khác /bin/sh, có cả

    1. Không thể tạo ra các tập lệnh có khả năng di động nhất có thể, do đó, việc chuyển đổi những gì /bin/shđược ánh xạ sang không phá vỡ mọi thứ; hoặc là

    2. Tập lệnh làm cho các tập lệnh không di động rõ ràng nhắm mục tiêu chương trình thông dịch chính xác , thay vì chỉ đơn giản là mong đợi /bin/shbản đồ đó đến nó.

  2. Có làm cho Almquist Debian shell lập bản đồ mặc định cho /bin/shthay cho Bourne Shell, để cho những kịch bản đó POSIX-tuân thủ QTI (hoặc, đúng hơn, chính sách Debian Manual tuân thủ QTI) chạy nhanh hơn.

Và tất nhiên một khi có được điều này, người ta có thể đưa nó đi xa hơn nhiều; chẳng hạn như xem xét sự đánh đổi hiệu quả của các lượt thích /bin/true/usr/bin/clearlà các kịch bản shell hoặc các chương trình được biên dịch. Nhưng điều đó vượt quá phạm vi của câu trả lời này, may mắn thay. ☺

Tất nhiên, không có cái nào là rất mới, thậm chí là dành riêng cho Unix. Quay trở lại trước thế kỷ, tôi đã viết và xuất bản một trình thông dịch dòng lệnh có cả hai hương vị "tương tác" và "không tương tác", giải thích chính sự phân chia này trong tài liệu của nó và lưu ý sự khác biệt giữa các biến môi trường COMSPECOS2_SHELLbiến. Tương tự như vậy, thảo luận về việc loại bỏ bashism trong System V rcvà các tập lệnh cài đặt / gỡ bỏ gói có từ những năm 1990.

đọc thêm


2
"Cuối cùng, Debian phải điều chỉnh một chút cho hệ vỏ Almquist, để thêm hỗ trợ cho một vài cấu trúc vỏ không phải POSIX đơn giản là được nhúng quá sâu và rộng rãi và quá hữu dụng để loại bỏ." - Liên kết nào trong số nhiều liên kết của bạn có thông tin về điều này? Âm thanh đó rất thú vị. :)
tự đại diện

3
IMHO, hiệu suất chỉ là một động lực để khiến mọi người đồng ý với những thay đổi. Lý do lớn ban đầu để thay đổi là bash liên tục phá vỡ tính tương thích ngược. Cá nhân tôi đã phải sửa các lỗi bash ít nhất 3 lần trong sự nghiệp của mình vì tập lệnh sẽ hoạt động ở một phiên bản bash nhưng không thành công ở phiên bản khác (thường xảy ra sau khi nâng cấp hệ điều hành). Dash không chỉ đơn thuần là một thông dịch viên nhanh hơn một chút. Nó cũng ổn định hơn nhiều về hành vi.
slebetman

Tôi sẽ quan tâm liệu các bình luận trong Schily Bourne Shelltrang man, xem schilytools.sourceforge.net/bosh.html có phù hợp để cho phép mọi người hiểu cách viết một tập lệnh di động (chỉ phụ thuộc vào Bourne Shell featuresnăm 1989). Những gì tôi đã làm là đề cập đến mọi cải tiến không có trong Bourne Shells cũ. BTW: Tôi cũng quan tâm để biết một danh sách các bashism trong dấu gạch ngang.
schily

8

Có bất kỳ lý do để có một shebang chỉ vào / bin / sh chứ không phải / bin / bash không?

Đúng. Câu trả lời tuyệt vời của @ Marco phác thảo điều này tốt.

Tôi nên sử dụng gì trong shebang của tôi?

Khi viết kịch bản của riêng bạn, bạn nên trỏ shebang đến điều chung nhất mà bạn đã thử nghiệm.

Trên hệ thống của tôi (Centos 6.6), shđược liên kết với bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Điều này có nghĩa là tôi luôn sử dụng #!/bin/bashtrong shebang của mình trừ khi tôi xác minh rằng tôi không có bashims trong kịch bản của mình.

Bằng cách đặt shebang cho #!/bin/shbạn, hứa hẹn rằng tập lệnh sẽ hoạt động với tất cả các cài đặt sh.

Đây là một lời hứa lớn hơn nhiều so với việc nói kịch bản sẽ hoạt động với bash.

Dưới đây là một ví dụ về tập lệnh sẽ hoạt động không chính xác tùy thuộc vào việc shtriển khai hệ thống đang sử dụng:

#!/bin/sh
n=1
a=$((++n))
echo $n

Khi sử dụng bashtập lệnh sẽ in:

2

Khi sử dụng dashtập lệnh sẽ in:

1

Nếu tôi muốn sử dụng #!/bin/shtôi cần phải làm gì?

  • Kiểm tra tập lệnh với checkbashisms- Lưu ý rằng điều này sẽ không tìm thấy tất cả các bashims. Nó không tìm thấy bashism trong kịch bản của tôi ở trên
  • Kiểm tra kịch bản bằng cách sử dụng shthực hiện khác . Tôi thường kiểm tra với dash, tuy nhiên tôi hy vọng rằng một số bashism hoặc dashims vẫn có thể lướt qua.

Các trang DashAsBinSh trên wiki Ubuntu có rất nhiều thông tin thú vị.


6
"Khi viết tập lệnh của riêng bạn, bạn nên trỏ shebang vào điều chung nhất mà bạn đã kiểm tra .... Bằng cách đặt shebang thành #! / Bin / sh, bạn hứa rằng tập lệnh sẽ hoạt động với tất cả các cài đặt của sh . " Điểm tuyệt vời . +1, và bạn đã khiến tôi suy nghĩ lại về cách tôi sẽ viết các shebang của mình cho tương lai. Cảm ơn bạn! :)
tự đại diện

2
Vâng, không phải tất cả các thực hiện /bin/sh; chỉ những người tuân thủ POSIX.
Blacklight Shining

4

Lý do duy nhất còn lại để viết tập lệnh shell, thay vì tập lệnh bằng ngôn ngữ mạnh mẽ và tiện dụng hơn, là nếu tính di động đối với các hệ thống cũ với một bộ phần mềm được cài đặt không xác định là quan trọng hơn bất kỳ yếu tố nào khác .

/bin/shlà trình thông dịch kịch bản lệnh một và duy nhất có sẵn trên mọi thứ tự gọi là Unix. Nhưng trên rất nhiều hệ thống cũ, /bin/shvà các tiện ích đi kèm thậm chí không tuân thủ thông số kỹ thuật "vỏ và tiện ích" POSIX.1-1996, hãy để mọi thứ hiện đại hơn. Các công cụ tuân thủ tiêu chuẩn là một tiện ích bổ sung tùy chọn, được cài đặt trong /usr/xpg4hoặc một số vị trí không rõ ràng như vậy. 1 Viết kịch bản cho ngôn ngữ hệ vỏ con di động thậm chí còn tẻ nhạt và dễ bị lỗi hơn so với kịch bản sang ngôn ngữ hệ vỏ POSIX. (Đọc qua configuretập lệnh do Autoconf tạo ra đôi khi nếu bạn không tin tôi. Chỉ cần thiết lập là đủ để thuyết phục bạn.)

Nhưng nếu bạn có thể giả sử bất kỳ trình thông dịch tập lệnh nào khác được cài đặt (ví dụ Bash) thì bạn có thể giả sử trình thông dịch cho ngôn ngữ kịch bản tốt hơn được cài đặt. Perl, ví dụ, có nhiều khả năng có sẵn hơn Bash.

Do đó, bạn không bao giờ nên viết một #! /bin/bashtập lệnh, bởi vì nếu đó là một tùy chọn, ngôn ngữ tốt hơn cũng là một tùy chọn.

1 Chẳng hạn, Solaris 10 trở lên đã vận chuyển vỏ Bourne ban đầu như /bin/sh. Tôi được thông báo rằng Solaris 11 đã cập nhật nó lên ksh93.


3
Trong ngôn ngữ nào bạn sẽ viết một kịch bản để khởi động một hệ thống? Hoặc bên trong một bộ định tuyến SOHO (hệ thống hạn chế)? Hay trong Android? Một vỏ sẽ có sẵn trong tất cả các trường hợp. Perl không.

1
Có một số điểm không chính xác về các phần liên quan đến Solaris trong câu trả lời của bạn. Trên Solaris 10 trở lên, không phải/bin/sh là POSIX.1-1996 mà thực sự là một cú pháp vỏ trước của cú pháp POSIX. Điều đó làm cho một shebang rất kém cho các kịch bản chạy với các bản phát hành này. Các tập lệnh di động trên Solaris sẽ sử dụng sẽ không dễ di chuyển trên các hệ điều hành khác. Trên Solaris mới nhất, Oracle Solaris 11 phát hành lần đầu năm 2011, là một phiên bản hiện đại tuân thủ các thông số kỹ thuật POSIX gần đây và có nhiều phần mở rộng hiện đại. #!/bin/sh#!/usr/xpg4/bin/sh/bin/shksh93
jlliagre

1
@BinaryZebra: "A shell" sẽ có sẵn, vâng. Nhưng bash không nhất thiết phải là vỏ đó (đặc biệt là hầu hết các bộ định tuyến SOHO sử dụng ashđược cung cấp với busybox) và tôi có xu hướng nghĩ zwol đúng là perl thường có sẵn hơn bash.
Ben Voigt

1
@BenVoigt Tôi đang bình luận về câu này "Lý do duy nhất còn lại để viết một kịch bản shell". Vẫn còn một số trường hợp cần shell cho một số tác vụ (không phải tất cả). Đó là một số trường hợp từ đỉnh đầu của tôi. OTOH Trong các hệ thống có đủ bộ nhớ (hầu hết tất cả các tiêu chuẩn hiện nay) và cài đặt đủ năng lượng Perl (hoặc Python, hoặc ....) khá nhanh chóng và dễ dàng. Tuy nhiên, tôi không ủng hộ cho bất kỳ vỏ cụ thể. Bạn đọc nó ở đâu trong bình luận của tôi?

2
Không đồng ý hoàn toàn với tuyên bố rất quan tâm và không chính xác của bạn rằng "nếu bashcó sẵn thì đó là một ngôn ngữ tốt hơn vì vậy bạn không bao giờ nên viết bất kỳ bashmã nào ." Ngoài ra, như @sixtyfootersdude chỉ ra, bạn nên luôn luôn sử dụng #!/bin/bashtrừ khi bạn đã kiểm tra rằng tập lệnh của bạn hoạt động với bất kỳ trình bao POSIX nào.
tự đại diện

0

Bạn thực sự nên sử dụng một trong hai

#! /bin/env sh

hoặc là

#! /bin/env bash

bằng cách đó, bạn gọi một trong hai shell bằng cách chúng được cài đặt trên hệ thống đó.

Để siêu an toàn ( ví dụ trong trường hợp khởi động lại một người dùng), hãy sử dụng shcách khác bash.


6
Từ câu trả lời này : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Điều này có lẽ cũng áp dụng cho shbash.
Jules

12
Không, bạn không nên sử dụng #!/bin/envbất cứ thứ gì trong một tập lệnh di động. Hoàn toàn hợp lý khi giả định rằng nó /bin/shtồn tại và là một vỏ hoạt động, tuân thủ POSIX. Mặt khác, không có hệ thống nào của tôi có a /bin/env.
Blacklight Shining

Cũng là một điểm tốt.
Jules

1
@Blacklight Shining chắc chắn là sai khi giả sử trình bao tương thích POSIX /bin/sh. POSIX không yêu cầu nó và thay vào đó xác định các quy tắc khác để có được môi trường tuân thủ POSIX trên nền tảng được chứng nhận POSIX.
Schily

4
/usr/bin/envkhông phải là phổ biến ...
vonbrand
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.