shebang và con đường


22

Tại sao một shebang cần một con đường?

Sai rồi

#!ruby

Chính xác

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

Hệ điều hành cần có thông tin liên quan đến đường dẫn của một lệnh đã đăng ký và tại sao nó vẫn mong đợi nó được đưa ra?

Câu trả lời:


22

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ì. $PATHlà 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ế.


5

Bạn có thể nhận được PATHngữ 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 PATHkhô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 đó

  1. /bin chứa các tệp thực thi cần thiết khi khởi động;
  2. /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;
  3. /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ở.
  4. ~/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 ~/bingọ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? PATHtì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/rubylà 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 #!.


0

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

4
Nhưng tại sao điều đó lại làm cho nó cần thiết? Bạn có thể chạy ruby ​​trực tiếp với ruby, nhưng điều đó không ngăn bạn chỉ định /home/user/myrubyinterpreternếu bạn muốn
Michael Mrozek

Quan điểm của Michael chính xác là những gì tôi đang hỏi.
sawa

0

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/shkhô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/awkso với /usr/bin/awk).

-2

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 đó.


Mối quan tâm này chỉ áp dụng nếu tập lệnh đang chạy với các đặc quyền nâng cao. Và điều đó không phổ biến, vì shebang và setxid không chơi tốt với nhau, và còn nhiều điều phải lo lắng hơn $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.
Gilles 'SO- ngừng trở nên xấu xa'

Quan điểm của bạn về setxid là hợp lệ, tuy nhiên đây là một vectơ tấn công hoàn toàn hữu ích nên chắc chắn không phải là một cảnh báo sai
Rory Alsop

1
Bạn có thể đưa ra một ví dụ về trường hợp PATHlà 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?
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles - +1 bạn có một điểm tốt, chắc chắn, vì nếu điều này bị phá vỡ, có lẽ có những cách khác cũng hợp lệ, tuy nhiên về những điều bị hỏng bạn có thể sửa, đây là một cách dễ dàng.
Rory Alsop
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.