Sử dụng #! / Bin / sh hoặc #! / Bin / bash để tương thích với Ubuntu-OSX và dễ sử dụng & POSIX


18

Tôi biết rằng tôi có thể sử dụng hoặc là dòng script đầu tiên để gọi shell mong muốn.

Sẽ #!/bin/shđược đề xuất nếu khả năng tương thích với tất cả các hệ thống unix là một yêu cầu tuyệt đối?

Trong trường hợp của tôi, hệ điều hành duy nhất tôi quan tâm là Ubuntu (Debian) và OSX. Cho rằng, tôi có thể sử dụng #!/bin/bashvà yên tâm rằng nó sẽ hoạt động trên cả hai hệ thống?
Điều này cũng sẽ làm cho việc sử dụng các tập lệnh với cú pháp hiện đại và rõ ràng hơn cho các lệnh dễ dàng hơn? Việc sử dụng #!/bin/shcũng liên quan đến việc sử dụng POSIX?


1
Có lẽ đáng chú ý là nhiều distro đã bắt đầu hợp nhất /bin/usr/bin. Kết quả là, có lẽ tốt hơn để sử dụng #!/usr/bin/env <shname>cho tính di động những ngày này.
HalosGhost

Câu trả lời:


15

Đối với người mới bắt đầu, nếu bạn có thể đưa ra giả định rằng Bash được cài đặt sẵn (theo hiểu biết của tôi là trường hợp trên tất cả các hệ thống bạn liệt kê), hãy sử dụng hàm băm sau để tương thích:

#!/usr/bin/env bash

cái này gọi bất cứ điều gì bashxảy ra để được cấu hình, bất kể nó ở trong /binhay /usr/local/bin.

Trong khi trên hầu hết các hệ thống trên một phạm vi rộng (bao gồm AIX, Solaris, một số hương vị BSD), bashkết thúc ở các địa điểm khác nhau, envluôn luôn kết thúc ở đó /usr/bin/env. Tuy nhiên, mánh khóe không phải của tôi mà là của tác giả cuốn sách Bash Cookbook.

Dù sao, vâng, Bash sẽ cho phép bạn sử dụng một số tính năng "hiện đại" giúp cuộc sống của bạn dễ dàng hơn.

Ví dụ: dấu ngoặc kép:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

trong khi theo phương ngữ vỏ truyền thống, bạn phải dùng đến:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

nhưng tốt nhất về dấu ngoặc kép là chúng cho phép các biểu thức chính quy cho khớp. Các Bash Hacker Wiki sẽ cung cấp cho bạn nhiều thủ đoạn theo hướng đó.

Bạn cũng có thể sử dụng các biểu thức khá thuận tiện như $((2**10))hoặc các biểu thức số học khác theo dòng với $((expression))cú pháp.

Sử dụng backticks cho subshells là tốt, mặc dù hơi lỗi thời. Nhưng khả năng lồng nhau của các $(command ...)yêu cầu sẽ thuận tiện hơn vì bạn sẽ không phải trốn thoát nhiều thứ ở các cấp độ khác nhau.

Đây chỉ là một vài điều mà Bash cung cấp cho bạn qua shcú pháp POSIX phổ biến .

Nhưng nếu bạn muốn có nhiều sức mạnh hơn trên trình bao (không chỉ trong các tập lệnh), hãy xem qua zsh.


Bash là một công cụ rất hữu ích nhưng hãy cẩn thận không sử dụng nó để bắt đầu các dịch vụ có thể dễ bị lỗi script script của Bash, ví dụ access.redhat.com/security/cve/CVE-2014-6271 . Bám sát shcho các nhiệm vụ như vậy.
Rick-777

1
Rick-777 rằng lỗ hổng đó đã bị thổi phồng quá mức và theo tôi nhận xét của bạn là FUD. Nếu một dịch vụ hệ thống chạy dưới bash, nó không dễ bị lỗi đó. Nó chỉ dễ bị lỗi đó nếu nó hủy bỏ quá trình bash trong khi cho phép người dùng từ xa truy cập trực tiếp vào một hoặc nhiều biến môi trường, như trong FastCGI, và thậm chí chỉ trên các phiên bản bash chưa được vá. Trên các hệ thống shđược liên kết đến bash, lỗ hổng sẽ không được giảm thiểu bằng cách sử dụng sh.
Điểm_Under

11

Trong Debian và Ubuntu, /bin/shdash, mà là một vỏ POSIX-compliant. Nếu bạn chỉ định #!/bin/sh, bạn phải tự giới hạn các câu lệnh POSIX trong tập lệnh của mình. (Ưu điểm là dashbắt đầu nhanh hơn bash, vì vậy tập lệnh của bạn có thể hoàn thành công việc trong thời gian ngắn hơn.)

Trên nhiều (nhất?) Hệ thống Linux khác, /bin/shbash, đó là lý do nhiều kịch bản được viết với #!/bin/shnhư dòng công việc của họ mặc dù họ sử dụng bashphần mở rộng.

Nếu bạn muốn sử dụng bashtiện ích mở rộng, cách tiếp cận an toàn nhất trên tất cả các hệ thống là chỉ định #!/bin/bash; theo cách đó bạn rõ ràng nêu rõ sự phụ thuộc của bạn vào bash. Bạn cần làm điều này trên Debian và Ubuntu. Là một phần thưởng bổ sung, khi bắt đầu /bin/sh bashhủy kích hoạt một số tiện ích mở rộng (xem mô tả về bashchế độ POSIX để biết chi tiết); vì vậy chỉ định #!/bin/bashlà cần thiết để có được lợi ích đầy đủ của bash.

Trên OS X /bin/bashcũng có sẵn, và /bin/shbash. Chỉ định #!/bin/bashsẽ làm việc tốt ở đó là tốt.


5

Có, cả OSX và Linux sẽ đi kèm /bin/bash. Bạn nên hoàn toàn an toàn. Tuy nhiên, đó không phải là POSIX. Shell POSIX có /bin/shtrên hầu hết các hệ thống (tất cả?) Và đó là cách tiếp cận di động nhất và là cách duy nhất để tương thích POSIX.

Lưu ý rằng trong khi trên nhiều hệ thống /bin/shtrỏ đến bash, trên các hệ thống khác, nó có thể trỏ đến các hệ vỏ khác nhau. dashVí dụ, đây là một liên kết tượng trưng cho Debian và Ubuntu. Ngoài ra, ngay cả khi /bin/shlà một liên kết đến bash, hành vi của shell thay đổi khi nó được gọi là sh(từ man bash, nhấn mạnh của tôi):

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. Khi được gọi dưới dạng vỏ đăng nhập tương tác hoặc vỏ không tương tác với tùy chọn --login, trước tiên, nó sẽ cố gắng đọc và thực thi các lệnh từ / etc / profile và ~ / .profile, theo thứ tự đó. Tùy chọn --noprofile có thể được sử dụng để ức chế hành vi này. Khi được gọi dưới dạng shell tương tác với tên sh, bash tìm ENV biến, mở rộng giá trị của nó nếu nó là
được định nghĩa và sử dụng giá trị mở rộng làm tên của tệp để đọc và thực thi. Do shell được gọi là sh không cố đọc và thực thi các lệnh từ bất kỳ tệp khởi động nào khác, nên tùy chọn --rcfile không có hiệu lực. Một vỏ không tương tác được gọi với tên sh không cố đọc bất kỳ tệp khởi động nào khác. Khi được gọi là sh, bash sẽ chuyển sang chế độ posix sau khi các tệp khởi động được đọc.


2

Nếu khả năng tương thích với "tất cả các hệ thống Unix" là một yêu cầu tuyệt đối - và nếu không, tại sao bạn lại viết một tập lệnh shell? - sau đó, vâng, bạn nên sử dụng #! /bin/sh, vì Bash không được đảm bảo để cài đặt ở bất cứ đâu , hãy để một mình /bin.

Nó thực sự nhiều, tệ hơn thế nhiều. Nếu bạn cần khả năng tương thích với tất cả các hệ thống Unix, bao gồm những thứ như Solaris và AIX đóng băng môi trường vỏ của chúng vào khoảng năm 1995. Điều đó có nghĩa là bạn phải sử dụng những thứ như sort +Ncú pháp lỗi thời - rằng các hệ thống mới hơn đã bị loại bỏ! Và nó cũng có nghĩa là không có hàm shell, không có mảng, không [[ ... ]], không ${foo#glob}, không $(( ... ))đối với số học, có thể không $( ... )thay thế lệnh kiểu, giới hạn trên nhỏ và không có giấy tờ về cách đầu vào lớn có thể nhận được, ...

Bạn có lẽ có thể nhận được ngay với không phiền với đó khả năng tương thích nhiều, nhưng nếu nó thậm chí còn là một vấn đề ở nơi đầu tiên, tôi khuyên bạn hãy xem xét một ngôn ngữ mà ít khủng khiếp hơn vỏ. Trình thông dịch Perl cơ bản có nhiều khả năng có sẵn hơn Bash.


Cảm ơn. Như đã nói ban đầu "Trong trường hợp của tôi, hệ điều hành duy nhất tôi quan tâm là Ubuntu (Debian) và OSX.". Đây là 2 hệ thống duy nhất tôi đã sử dụng (và tôi sử dụng chúng rất nhiều) trong 5 năm qua, vì vậy đó là 'tại sao' tôi đang viết một kịch bản shell chỉ hoạt động trên chúng. Tôi hoàn toàn không cần một kịch bản phổ quát và những hạn chế mà nó sẽ đưa ra.
Michael Durrant

@MichaelDurrant Trong trường hợp đó, bạn không cần và không nên viết kịch bản shell. Thay vào đó, bạn nên sử dụng bất kỳ ngôn ngữ kịch bản tốt hơn nào là một tùy chọn khi bạn không cần tổng số tính di động.
zwol 6/2/2015
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.