Loại đường dẫn nào trong shebang được ưa thích hơn?


20

Trong các tập lệnh, dòng đầu tiên sẽ chỉ định đường dẫn đến trình thông dịch.
Nhưng trên các máy chủ khác nhau Linux, Unix hoặc BSD, đường dẫn này có thể khác nhau.

Điều gì là thích hợp hơn?

#!/usr/bin/env bash 

hoặc là

#!/bin/bash 

Câu trả lời:


22

Nếu bạn muốn sử dụng phiên bản cài đặt hệ thống của một trình thông dịch đã cho được cài đặt ở một vị trí tiêu chuẩn, hãy sử dụng đường dẫn trực tiếp. Nếu bạn muốn sử dụng bất kỳ phiên bản trình thông dịch nào xuất hiện đầu tiên trong người dùng $PATH, hãy sử dụng #!/usr/bin/env ....

Các envlệnh gọi một lệnh cụ thể, cho phép bạn thiết lập hoặc biến môi trường unset:

env FOO=BAR do-something
env DISPLAY=:0.0 xterm -ls &

Nếu bạn không chỉ định bất kỳ biến môi trường hoặc các tùy chọn khác, nó sẽ chỉ gọi lệnh được đặt tên. (Sử dụng nó theo cách này được cho là một chút hack.)

Mục đích của việc viết shebang như

#!/usr/bin/env interp

là để gọi bất cứ điều gì interpxuất hiện đầu tiên trong $PATH.

Đây có nghĩa là bạn không cần phải biết, khi viết kịch bản, chính xác nơi interplà (nói, nếu nó có thể là một trong hai /bin, /usr/binhoặc /usr/local/bin). Tất nhiên bạn phải biết rằng env/usr/bin/env, nhưng điều đó có vẻ là hợp lý phổ quát.

Ưu điểm là nó gọi bất kỳ phiên bản nào của trình thông dịch xuất hiện đầu tiên trong người dùng $PATH. Các bất lợi là nó gọi bất cứ phiên bản của thông dịch viên xuất hiện đầu tiên trong sử dụng của $PATH.

Ví dụ: giả sử tôi đã cài đặt bản dựng cá nhân trong perlthư mục nhà của mình $HOME/bin/perl, và, tôi có $HOME/binở phía trước $PATH. Nếu tôi chạy một kịch bản có shebang

#!/usr/bin/env perl

sau đó nó sẽ được chạy với perlchương trình thực thi được cài đặt của riêng tôi - có thể không phải là một điều tốt. Tác giả của kịch bản có lẽ đã không thử nghiệm nó với Perl cạnh sáng mà tôi đã xây dựng từ nguồn một tháng trước.

Đối với một cái gì đó như Perl hoặc Bash có khả năng được cài đặt ở một vị trí nhất quán trên hầu hết các hệ thống ( /usr/bin/perl/bin/bash, tương ứng), tôi sẽ sử dụng đường dẫn trực tiếp đến lệnh. Đối với một cái gì đó tối nghĩa hơn có thể được cài đặt khác nhau trên các hệ thống khác nhau, tôi sẽ sử dụng /usr/bin/envthủ thuật hoặc tôi sẽ viết một trình cài đặt điều chỉnh dòng shebang khi tập lệnh đang được cài đặt. (Tôi đã từng phải làm điều đó cho các tập lệnh Perl của mình.)

CẬP NHẬT: Tôi đã đi sâu hơn một chút vào câu trả lời cho câu hỏi này trên trang web Unix & Linux .


Tôi mới bắt đầu tìm kiếm Ruby và tôi thấy rằng quy ước trong Ruby là bắt đầu với [code] #! / Usr / bin / env ruby ​​[/ code] vì mục đích di động. Một số lưu ý rằng điều này gây khó khăn cho việc cung cấp các đối số dòng lệnh cho trình thông dịch ruby, chẳng hạn như '-w', đây cũng sẽ là một vấn đề đối với Perl.
bgvaughan

@bgvaughan Đối với Perl, ngày nay truyền thống chỉ sử dụng #!/usr/bin/perlvà sau đó sử dụng use strict; use warnings;trong phần thân của tập lệnh chứ không phải #!/usr/bin/perl -w. Nhưng -Tphải ở trên shebang.
Keith Thompson

vậy tại sao không sử dụng #! perl nếu chúng ta chỉ muốn cái đầu tiên trên đường dẫn?
wheredidthatnamecome từ

@wheredidthatnamecomefrom: Bởi vì điều đó không hiệu quả. Việc điều trị của #!dòng không sử dụng $PATH. Bạn phải xác định đường dẫn của trình thông dịch. (Tôi mới nhận ra rằng, ít nhất là trên hệ thống của mình, nó có thể là một con đường tương đối, nhưng điều đó hiếm khi hữu ích.)
Keith Thompson

6

Thực hành tốt nhất là đây:

#!/usr/bin/env bash 
#!/usr/bin/env sh
#!/usr/bin/env python

Và cứ thế ...

Khi Ubuntu lần đầu tiên bắt đầu sử dụng dấu gạch ngang, một số tập lệnh đã bị hỏng. Đã có cuộc thảo luận về nó. Hầu hết các tập lệnh được viết #!/bin/shlà một liên kết đến / bin / bash. Sự đồng thuận là thế này: người viết kịch bản có trách nhiệm chỉ định người phiên dịch. Do đó, nếu tập lệnh của bạn phải luôn được gọi bằng BASH, hãy chỉ định nó từ môi trường. Điều này giúp bạn không phải đoán đường dẫn, khác với các hệ thống Unix / Linux khác nhau. Ngoài ra, nó sẽ hoạt động nếu ngày mai / bin / sh trở thành một liên kết đến một số shell khác như / bin / wthsh hoặc một số điều vô nghĩa khác.


Các sửa chữa rõ ràng thay thế cho vấn đề dash là viết #!/bin/bash. Tôi đồng ý rằng người viết kịch bản chịu trách nhiệm chỉ định người phiên dịch, nhưng tất cả điều đó có nghĩa là nếu bạn cần bash, hãy nói bash không sh
Martin Bonner hỗ trợ Monica

1

FYI nó là một shee-bang #!, bạn cần #. Bạn sử dụng dòng này để xác định trình thông dịch nào để chạy tập lệnh.

Theo mặc định, Ubuntu liên kết /bin/shđến dấu gạch ngang

Tùy thuộc vào mức độ bạn có thể muốn biết về dấu gạch ngang và tại sao dấu gạch ngang được sử dụng cho hệ thống hoặc vỏ deamon xem:

cyberciti.biz dash

Trang người dùng Ubuntu dash

Bash là shell mặc định được sử dụng bởi hầu hết người dùng Linux và có các tính năng khác nhau sau đó gạch ngang. Một tập lệnh được viết cho bash có thể hoặc không thể chạy đúng nếu chạy bằng dấu gạch ngang, tập lệnh càng phức tạp thì càng ít khả năng nó sẽ chạy.

Kịch bản được viết cho perl, python, v.v. sẽ không chạy hoàn toàn với /bin/shhoặc /bin/bash.

Vì vậy, khi bạn viết một tập lệnh, bạn xác định trình thông dịch nào sẽ được sử dụng với shee-bang

Việc lựa chọn những gì để sử dụng được thực hiện bởi tác giả của kịch bản, và một cái không tốt hơn cái khác, tất cả chúng đều có các tính năng, ưu điểm và nhược điểm khác nhau.


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.