shell script vẫn hoạt động mà không có #! (dòng sha-bang)


10

Tôi chưa quen với shell script và nhiều cuốn sách đã viết sử dụng dòng #! (Sha-bang) khi bắt đầu tập lệnh để gọi trình thông dịch. Và điều này sẽ gọi shell mới cho script và thực hiện dòng phiên dịch theo dòng. Nhưng một kịch bản cơ bản của tôi vẫn đang chạy mà không có dòng ma thuật.

vì vậy câu hỏi của tôi là:

  • từ đâu kịch bản cơ bản của tôi có được thông dịch viên.
  • làm thế nào kịch bản quản lý để xác định vị trí thông dịch viên.

Bây giờ hãy để tôi nói với bạn về kịch bản cơ bản của tôi, nó chỉ chứa dòng sau:

echo "kịch bản cơ bản không có dòng ma thuật"


Câu trả lời:


3

Nếu dòng ma thuật không được cung cấp, một vỏ mặc định được sử dụng để chạy tập lệnh. Shell mặc định này có thể là shell Bourne (sh) là trường hợp trong một số hương vị, tuy nhiên, trong một số hương vị khác, shell mặc định được sử dụng giống như shell đăng nhập để thực thi nó. Vấn đề là: Đừng để nó vào hệ thống để quyết định shell, luôn cung cấp shell mà bạn muốn trong dòng đầu tiên.


1
yup..may là shell hiện tại của tôi đang gọi shell mặc định cho shell script không có số ma thuật.
dùng1678213

1
@ user1678213 Vâng, đó là vỏ của bạn (chứ không phải kernel) đang làm điều này.
Gilles 'SO- ngừng trở nên xấu xa'

1
Tôi tin rằng POSIX bắt buộc / bin / sh được sử dụng trong trường hợp này.
vonbrand

2
@vonbrand Đây là một quan niệm sai lầm phổ biến. POSIX không bắt buộc phải có vỏ POSIX /bin/sh, chỉ là shtệp thực thi đầu tiên được tìm thấy trong khi khám phá một PATH phù hợp.
jlliagre

3
Điều đó không chính xác, nó không bao giờ là "vỏ đăng nhập" được sử dụng để thực thi nó. Điều có thể xảy ra là shell gọi (nếu script được gọi từ shell) có thể có một đứa trẻ tự giải thích nó.
Stéphane Chazelas

8

Khi bạn thực hiện một chương trình, kernel sẽ kiểm tra xem nó có bắt đầu bằng một chuỗi byte ma thuật hay không . Nếu tệp thực thi bắt đầu bằng #!, kernel sẽ hiểu phần còn lại của dòng là tên của trình thông dịch. Nếu tệp thực thi bắt đầu bằng \177ELF(trong đó \177là byte 127), nó sẽ tải tệp dưới dạng thực thi ELF ; đó là loại bình thường trên hầu hết các hệ thống unix hiện nay.

Nếu kernel không nhận ra định dạng tệp, nó sẽ từ chối thực thi tệp và trả về lỗi ENOEXEC (lỗi định dạng Exec). Khi shell thông báo điều đó, nó sẽ tự thực hiện chương trình như một kịch bản shell.

Để chứng kiến ​​điều này trong thực tế, hãy thêm một vài lệnh vào tập lệnh của bạn:

ps l $$
ls -l /proc/$$/exe
echo hello

(Cái này dành cho Linux, điều chỉnh cho các thông báo khác.) Sau đó thử chạy tập lệnh đó từ nhiều shell khác nhau. Bạn sẽ thấy rằng một số shell sinh ra một phiên bản mới của chính chúng để thực thi tập lệnh (bash, ksh93) trong khi một số khác sinh ra /bin/sh(dash, pdksh, zsh).


Tôi tìm kiếm gì với ls -llệnh của bạn ? Cái này: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-? Nếu vậy, nó nói gì? Ngoài ra, nhận thấy tôi có SHELL=/bin/bashtrên env, nhưng thay đổi nó dường như không thay đổi hành vi. Có lẽ nó không liên quan?
Emanuel Berg

có vẻ như bạn đang thay đổi biến shell "SHELL". nếu có, thì bạn chỉ đang kiểm tra giá trị của biến shell SHELL.it sẽ không trả lời shell của bạn.
dùng1678213

2
@EmanuelBerg Có ( ls -l /proc/$$/exetrên thực tế tôi nên viết ). Các exeliên kết trỏ đến trình bao thực thi tập lệnh của bạn. Khi bạn chạy tập lệnh của mình, bạn sẽ thấy rằng nó bash diễn giải tập lệnh. Nếu bạn chạy nó từ ví dụ pdksh, nó sẽ chạy /bin/sh. Tôi không biết bất kỳ shell nào sử dụng SHELLbiến môi trường hoặc shell đăng nhập trong trường hợp đó.
Gilles 'SO- ngừng trở nên xấu xa'

2
@ user1678213 Thay đổi shell trong /etc/passwdthay đổi shell nào được thực thi khi bạn đăng nhập qua SSH hoặc trên bảng điều khiển văn bản. Nó không thay đổi shell nào có thể thực thi các script.
Gilles 'SO- ngừng trở nên xấu xa'

2
@ user1678213 Tôi đã xác minh những gì tôi đã viết ở đây bằng cách chạy thử nghiệm. Không có trình bao nào mà tôi đã kiểm tra nhìn vào /etc/passwdđể quyết định sử dụng trình bao nào, chúng sẽ phân tách một thể hiện của chính chúng hoặc được thực thi /bin/sh.
Gilles 'SO- ngừng trở nên xấu xa'

-2

Đây có thể là một trong 3 khả năng sau:

  1. Bạn đang gọi kịch bản trực tiếp với trình thông dịch, IE: bash script.sh

  2. Tên của tệp tập lệnh có phần mở rộng .sh, giúp hệ thống tìm chương trình mặc định cho loại tệp này

  3. Môi trường shell mà bạn đang sử dụng đang tự thực hiện 'echo', vì tôi chỉ có thể đoán rằng tệp script có thể thực thi được. Ví dụ, nếu bạn sẽ sử dụng bash shell và có một lệnh trong tệp của bạn chỉ được sử dụng bởi ksh, thì bạn sẽ thấy rằng nó sẽ không hoạt động.

Chúc may mắn!


3
tôi cũng không gọi nó bằng bash hay với bất kỳ phần mở rộng nào.
dùng1678213

1
và môi trường shell không thực thi nó bởi vì khi tôi gọi lệnh ps sau khi gọi script của tôi. Lệnh ps hiển thị hai bash process. nghĩa là có hai bash đang chạy. một cái là bash shell của tôi và cái kia là bash cho basic_script của tôi
user1678213

1
2: kernel sẽ không làm gì như vậy. Zsh có thể làm điều đó, và bash có thể được xoắn để làm điều đó. 3: Có, nhưng nó thay đổi một chút giữa các vỏ, xem câu trả lời của tôi.
Gilles 'SO- ngừng trở nên xấu xa'
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.