Cuộc exec
gọi hệ thống của nhân Linux hiểu rõ shebangs ( #!
)
Khi bạn làm trên bash:
./something
trên Linux, điều này gọi cuộc gọi exec
hệ thống với đường dẫn ./something
.
Dòng này của kernel được gọi trên tệp được chuyển đến exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
Nó đọc các byte đầu tiên của tệp và so sánh chúng với #!
.
Nếu so sánh là đúng, thì phần còn lại của dòng được phân tích cú pháp bởi nhân Linux, điều này thực hiện một exec
cuộc gọi khác với đường dẫn /usr/bin/env python
và tệp hiện tại làm đối số đầu tiên:
/usr/bin/env python /path/to/script.py
và điều này hoạt động cho bất kỳ ngôn ngữ kịch bản sử dụng #
như một nhân vật bình luận.
Và vâng, bạn có thể tạo một vòng lặp vô hạn với:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a
Bash nhận ra lỗi:
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#!
tình cờ có thể đọc được, nhưng điều đó là không bắt buộc.
Nếu tệp bắt đầu với các byte khác nhau, thì lệnh exec
gọi hệ thống sẽ sử dụng một trình xử lý khác. Trình xử lý tích hợp quan trọng nhất khác dành cho các tệp thực thi ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 để kiểm tra byte 7f 45 4c 46
(cũng có thể là con người có thể đọc được .ELF
). Hãy xác nhận rằng bằng cách đọc 4 byte đầu tiên /bin/ls
, đây là tệp thực thi ELF:
head -c 4 "$(which ls)" | hd
đầu ra:
00000000 7f 45 4c 46 |.ELF|
00000004
Vì vậy, khi kernel nhìn thấy các byte đó, nó sẽ lấy tệp ELF, đặt nó vào bộ nhớ một cách chính xác và bắt đầu một quy trình mới với nó. Xem thêm: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-ricky-under-linux/31394861#31394861
Cuối cùng, bạn có thể thêm trình xử lý shebang của riêng bạn với binfmt_misc
cơ chế. Ví dụ: bạn có thể thêm một trình xử lý tùy chỉnh cho .jar
các tệp . Cơ chế này thậm chí hỗ trợ xử lý bằng cách mở rộng tập tin. Một ứng dụng khác là chạy trong suốt các tệp thực thi của một kiến trúc khác với QEMU .
Tuy nhiên, tôi không nghĩ POSIX chỉ định shebang: https://unix.stackexchange.com/a/346214/32558 , mặc dù nó đề cập đến nó trong các phần hợp lý và ở dạng "nếu các tập lệnh thực thi được hệ thống hỗ trợ có thể xảy ra".
chmod +x my_shell_script.sh ; /path/to/my_shell_script.sh # or ./my_shell_script.sh if you happen to be in its directory