Tại sao bạn cần đặt #! / Bin / bash vào đầu tệp tập lệnh?


486

Tôi đã tạo ra các kịch bản Bash trước đây và tất cả chúng đều chạy tốt mà không cần #!/bin/bashngay từ đầu.

Điểm của việc đưa nó vào là gì? Mọi thứ sẽ khác đi?

Ngoài ra, làm thế nào để bạn phát âm #? Tôi biết đó !được phát âm là "bang."

Làm thế nào được #!phát âm?


8
Bạn không cần và bạn không nên trừ khi bạn không có lựa chọn nào khác. Sử dụng '#! / Bin / sh' trong khi bạn có thể và tìm hiểu về sự khác biệt giữa vỏ (POSIX) và bash. Sẽ đến một ngày trước khi sơ yếu lý lịch của bạn phát triển quá lâu khi bạn sẽ thấy mình trên một hệ thống có vỏ khác và bạn vẫn muốn các tập lệnh của mình hoạt động.
Jens

50
Nó được phát âm là "Hash-Bang" hoặc "She-Bang".
Beachhouse

22
Tôi nghĩ rằng đáng lưu ý rằng điều này chỉ được thực hiện nếu bạn chạy tập lệnh của mình dưới dạng thực thi. Vì vậy, nếu bạn đặt cờ thực thi và sau đó gõ ./yourscript.extension, ví dụ, ./helloworld.pyhay ./helloworld.sh, nó sẽ tìm kiếm các thông dịch viên tại đó dòng trên cùng, đó sẽ là #!/bin/pythonhay !#/bin/bash, trong khi đó khi thực hiện các kịch bản như python helloworld.py, dòng đầu tiên sẽ không được quan sát bởi vì nó được nhận xét ngoài. Vì vậy, nó là một chuỗi đặc biệt cho shell / kernel.
JFA

@JFA có sự thay đổi về trình tự giữa bash và python, khi sử dụng! # Cho python và #! cho bash?
AAI

1
@AjeyaAnand không phải là một loại nhầm, bắt tốt
JFA

Câu trả lời:


426

Đó là một quy ước để shell * nix biết loại trình thông dịch nào sẽ chạy.

Ví dụ, các hương vị ATT cũ hơn được mặc định là sh (shell Bourne), trong khi các phiên bản BSD cũ hơn được mặc định là csh (shell C).

Ngay cả ngày nay (nơi hầu hết các hệ thống chạy bash, "Bourne Again Shell" ), các tập lệnh có thể ở dạng bash, python, perl, ruby, PHP, v.v., v.v. Ví dụ, bạn có thể thấy #!/bin/perlhoặc #!/bin/perl5.

PS: Dấu chấm than ( !) được gọi một cách trìu mến là "bang" . Biểu tượng vỏ bình luận ( #) đôi khi được gọi là "băm" .

PPS: Ghi - dưới * nix, kết hợp một hậu tố với một kiểu tập tin chỉ là một ước , không phải là một "quy tắc" . Một thực thi có thể là một chương trình nhị phân, bất kỳ một trong một triệu loại tập lệnh và những thứ khác là tốt. Do đó nhu cầu #!/bin/bash.


1
Tôi phát hiện ra về một thứ khác hữu ích, $ #. Cái đó gọi là gì?
nút ninja

91
Shebang không phải là một quy ước shell , nó được giải thích bởi kernel khi xử lý tòa nhà execve(2); Vì vậy, shebang là một quy ước hạt nhân , không phải là một vỏ.
Basile Starynkevitch

10
Ngoài ra, nó giúp một số trình soạn thảo như Vim xác định ngôn ngữ để tô sáng cú pháp nếu tệp không có phần mở rộng. Không có shebang, Vim sẽ hiển thị tập lệnh bash giống như tệp văn bản thuần túy.
Aaron Blenkush

1
Nó làm cho tôi tự hỏi liệu bạn cần phải thêm #!/bin/shvào những thứ như .profilevà các công cụ mà chạy onload
Kolob Canyon

5
Vậy ... hash-bang-slash-bin-slash-bash ?
Bernat

134

Nói chính xác hơn là shebang #! , khi đó là hai byte đầu tiên của tệp thực thi ( x chế độ ), được diễn giải bằng lệnh gọi hệ thống execve (2) (thực thi các chương trình). Nhưng đặc tả POSIXexecve không đề cập đến shebang.

Nó phải được theo sau bởi một đường dẫn tệp của một trình thông dịch thực thi (mà BTW thậm chí có thể là tương đối, nhưng thường là tuyệt đối).

Một thủ thuật rất hay (hoặc có lẽ không quá thoải mái một) để tìm một thông dịch viên (ví dụ python) ở người dùng của $PATHlà sử dụng envchương trình (luôn luôn ở /usr/bin/envtrên tất cả Linux) như ví dụ

 #!/usr/bin/env python

Bất kỳ thực thi ELF có thể là một thông dịch viên. Bạn thậm chí có thể sử dụng #!/bin/cathoặc #!/bin/truenếu bạn muốn! (nhưng đó sẽ là thường vô dụng)


8
Xem câu hỏi này để thảo luận về #!/usr/bin/envhack.
Keith Thompson

Nếu tôi muốn truyền một đối số cho python, làm thế nào để tôi thực sự làm điều đó #!/usr/bin/env bash -x. Làm thế nào để làm điều đó ?
Ấn Độwebdevil

đơn giản của nó i bản thân mình tìm thấy nó, chỉ cần thêm param sau đó#!/usr/bin/env bash -x
indianwebdevil

bashhầu như luôn luôn ở /bin/bashđó vì vậy #!/bin/bash -x
shebang

49

Nó được gọi là một công việc . Trong unix-speak, # được gọi là sharp (như trong âm nhạc) hoặc hash (như hashtags trên twitter) và! được gọi là bang. (Bạn thực sự có thể tham khảo lệnh shell trước đó của bạn với !!, được gọi là bang-bang). Vì vậy, khi đặt lại với nhau, bạn nhận được haSH-BANG, hoặc shebang.

Phần sau #! cho Unix biết chương trình nào sẽ sử dụng để chạy nó. Nếu nó không được chỉ định, nó sẽ cố gắng với bash (hoặc sh, hoặc zsh, hoặc bất cứ biến $ SHELL của bạn là) nhưng nếu nó ở đó nó sẽ sử dụng chương trình đó. Thêm vào đó, # là một lời nhận xét trong hầu hết các ngôn ngữ, do đó, dòng bị bỏ qua trong việc thực hiện tiếp theo.


2
Nếu tôi đã ở trong bash, nó có bắt đầu một bash khác không nếu nó thấy #! / Bin / bash? Điều gì xảy ra nếu tôi đã ở trong bash và tôi bỏ nó? Có sự khác biệt nào không?
nút ninja

2
@javascriptninja hoặc là nó bắt đầu một vỏ bash mới. Trong trường hợp bash, thực sự không có gì khác biệt, miễn là bạn đang sử dụng bash. Shebang chỉ thực sự quan trọng nếu (a) bạn cần chạy trong một thứ không chỉ là vỏ, như python hoặc perl, hoặc (b) bạn không sử dụng bash shell (tức là bạn sử dụng zsh) nhưng bạn cần phải chạy một cái gì đó đòi hỏi phải được chạy trong bash.
austin1howard

Tuy nhiên, theo ý kiến của tôi nó thực hành tốt để bao gồm các công việc, chỉ để ai đó đọc mã biết những gì đang xảy ra.
austin1howard

2
Sai: execve(2)syscall không sử dụng $SHELLbiến. Nó là kernel đang diễn giải shebang.
Basile Starynkevitch

1
@BasileStarynkevitch là chính xác, trình tải elf trong kernel diễn giải shebang. Tôi đã nói rằng $ SHELL sẽ được sử dụng nếu không có shebang được cung cấp.
austin1howard

19

Các công việc là một chỉ thị cho bộ nạp để sử dụng chương trình được quy định sau #!khi người phiên dịch cho các tập tin trong câu hỏi khi bạn cố gắng thực hiện nó. Vì vậy, nếu bạn cố gắng chạy một tập tin gọi foo.shtrong đó có #!/bin/bashở phía trên, các lệnh thực tế mà chạy là /bin/bash foo.sh. Đây là một cách linh hoạt sử dụng các thông dịch viên khác nhau cho các chương trình khác nhau. Đây là một cái gì đó được triển khai ở cấp hệ thống và API cấp độ người dùng là quy ước shebang.

Cũng đáng để biết rằng shebang là một con số ma thuật - một con người có thể đọc được, xác định tệp là tập lệnh cho trình thông dịch đã cho.

Quan điểm của bạn về việc nó "hoạt động" ngay cả khi không có shebang chỉ là do chương trình được đề cập là một tập lệnh shell được viết cho cùng trình bao với trình bao bạn đang sử dụng. Ví dụ: bạn rất có thể viết một tệp javascript và sau đó đặt một #! /usr/bin/js(hoặc một cái gì đó tương tự) để có một đoạn mã "Shell script" javascript.


18

Hệ điều hành lấy shell mặc định để chạy script shell của bạn. để nhắc đến con đường vỏ ở phần đầu của kịch bản, bạn đang yêu cầu hệ điều hành để sử dụng lớp vỏ đặc biệt. Nó cũng hữu ích cho tính di động .


15

Mỗi phân phối có một vỏ mặc định. Bash là mặc định trên phần lớn các hệ thống. Nếu bạn tình cờ làm việc trên một hệ thống có vỏ mặc định khác, thì các tập lệnh có thể không hoạt động như dự định nếu chúng được viết riêng cho Bash.

Bash đã phát triển qua nhiều năm lấy mã từ kshsh.

Thêm vào #!/bin/bashnhư là dòng đầu tiên của tập lệnh của bạn, yêu cầu HĐH gọi lệnh được chỉ định shellđể thực thi các lệnh tiếp theo trong tập lệnh.

#! thường được gọi là "băm-bang", "cô-bang" hoặc "sha-bang".


9

Nó được gọi là một công việc . Nó bao gồm một ký hiệu số và ký tự dấu chấm than (#!), Theo sau là đường dẫn đầy đủ đến trình thông dịch, chẳng hạn như / bin / bash. Tất cả các tập lệnh trong UNIX và Linux thực thi bằng trình thông dịch được chỉ định trên dòng đầu tiên.



0

Nó có thể hữu ích cho ai đó sử dụng một hệ thống khác không có sẵn thư viện đó. Nếu mà không được khai báo và bạn có một số chức năng trong kịch bản của bạn không được hỗ trợ bởi hệ thống đó, bạn nên tuyên bố # / bin / bash. Tôi đã gặp vấn đề này trước đây tại nơi làm việc và bây giờ tôi chỉ đưa nó vào như một thực tiễn.

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.