Câu trả lời:
Có lẽ để giữ cho hạt nhân đơn giản hơn. Tôi không nghĩ kernel đã tìm kiếm đường dẫn của bạn để tìm một tệp thực thi. Điều đó được xử lý bởi thư viện C. #!
việc xử lý được thực hiện trong kernel, không sử dụng thư viện C tiêu chuẩn.
Ngoài ra, tôi không nghĩ rằng hạt nhân có một khái niệm về con đường của bạn là gì. $PATH
là một biến môi trường và chỉ các quá trình có môi trường. Hạt nhân không. Tôi cho rằng nó có thể truy cập vào môi trường của quá trình đã thực hiện, nhưng tôi không nghĩ bất cứ điều gì hiện tại trong kernel đều truy cập các biến môi trường như thế.
Bạn có thể nhận được PATH
ngữ nghĩa học tập bằng cách sử dụng env
, vì vậy:
#!/usr/bin/env ruby
có ngữ nghĩa mà bạn muốn từ
#!ruby
Lý do phụ thuộc vào việc PATH
không được coi là thông lệ tốt là tập lệnh có thể không đưa ra giả định nào về nội dung của biến môi trường PATH, phá vỡ "mô hình phụ thuộc tuần tự" của nhị phân trong đó
/bin
chứa các tệp thực thi cần thiết khi khởi động;/usr/bin
chứa các tệp thực thi khác được sử dụng bởi cài đặt hệ điều hành;/usr/local/bin
chứa các tệp thực thi được cài đặt bởi quản trị viên hệ thống không phải là một phần của HĐH cơ sở.~/bin
chứa các tệp thực thi của chính người dùng.Mỗi cấp độ không nên giả sử sự tồn tại của các nhị phân sau này trong chuỗi, đó là "ứng dụng" nhiều hơn nhưng có thể dựa vào các nhị phân trước đó, đó là "nguyên tắc cơ bản" hơn. Và biến PATH có xu hướng chạy từ ứng dụng sang cơ bản, đó là hướng ngược lại với sự phụ thuộc tự nhiên ở trên.
Để minh họa vấn đề, hãy tự hỏi điều gì xảy ra nếu một kịch bản ~/bin
gọi ra một kịch bản trong /usr/local/bin
đó gọi Ruby? Tập lệnh đó có nên phụ thuộc vào phiên bản cài đặt hệ điều hành tại /usr/bin/ruby
, hoặc vào bản sao cá nhân mà người dùng tình cờ có tại ~/bin/ruby
? PATH
tìm kiếm đưa ra ngữ nghĩa không thể đoán trước được liên kết với cái sau (có thể ~/bin/ruby
là một liên kết tượng trưng bị hỏng), trong khi nướng trong đường dẫn để #!
đưa ra cái trước.
Thực sự không có bất kỳ "hệ điều hành ... độc lập với nền tảng nào khác liên quan đến đường dẫn cho lệnh đã đăng ký", vì vậy điều đơn giản nhất là nhấn mạnh vào đường dẫn được cung cấp trong #!
.
Tôi tin rằng bạn có thể chỉ định một thông dịch viên thay thế nếu bạn cần hoặc muốn. Ví dụ:
#!/home/user/myrubyinterpreter
Thường thấy hơn với các kịch bản shell:
#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Từ cuốn sách Classic Shell Scripting :
Shell script thường bắt đầu bằng
#! /bin/sh
. Sử dụng đường dẫn đến trình bao tuân thủ POSIX nếu bạn/bin/sh
không tuân thủ POSIX. Ngoài ra còn có một số "gotchas" cấp thấp để coi chừng:
- Bạn phải biết tên đường dẫn đầy đủ đến trình thông dịch sẽ được chạy. Điều này có thể ngăn chặn tính di động của nhà cung cấp chéo, vì các nhà cung cấp khác nhau đặt mọi thứ ở những nơi khác nhau (ví dụ,
/bin/awk
so với/usr/bin/awk
).
Có những lý do khác, nhưng từ góc độ bảo mật, tôi sẽ không bao giờ muốn một kịch bản đưa ra các giả định về đường dẫn chính xác. Điều gì nếu nó sai và nó chạy shell hoặc trình thông dịch sai? Một trong đó đã được chèn bởi một người dùng độc hại? Hoặc nếu nó dựa vào một vỏ cụ thể và sẽ sụp đổ nếu sử dụng vỏ sai?
Người dùng có thể loay hoay với đường dẫn của họ và phá vỡ nội dung - không tin tưởng người dùng :-) Tôi đã thực hiện nhiều cuộc tấn công dựa vào người dùng làm sai với đường dẫn của họ - thường nhận được mọi thứ theo thứ tự sai - vì vậy tôi có thể lật đổ một cuộc gọi kịch bản bình thường.
Vâng, tôi biết nếu bạn đã tự viết kịch bản, bạn hoàn toàn có thể tuyên bố rằng bạn đã sắp xếp đường dẫn của riêng mình, nhưng một thông dịch viên không thể đưa ra những quyết định đó.
$PATH
. . Nếu không có đặc quyền nâng cao, nếu LD_PRELOAD
được sử dụng thì sao? PS bị từ chối vì đưa ra cảnh báo sai về bảo mật là bất lợi cho an ninh.
PATH
là một vectơ tấn công và không có nhiều vectơ tấn công khác mà toàn bộ cách tiếp cận nên được xem xét lại?
ruby
, nhưng điều đó không ngăn bạn chỉ định/home/user/myrubyinterpreter
nếu bạn muốn