Làm thế nào để tra cứu trong $ PATH hoạt động dưới mui xe?


8

Có quá nhiều bài viết / tài nguyên trên web dạy cho mọi người CÁCH đặt biến môi trường PATHđể họ có thể sử dụng tay ngắn javahoặc pythonvv thay vì đường dẫn tuyệt đối trong giao diện dòng lệnh.

Điều tôi quan tâm cần biết là những gì đằng sau hậu trường khi chúng ta nhập lệnh và nhấn enter (tương tự như những gì xảy ra khi bạn nhập URL trong trình duyệt ).

Đây là dự đoán của tôi:

  1. đọc lệnh (phân tích cú pháp / tiền xử lý stdin để có được các đối số đúng $@)
  2. tra cứu lệnh
  3. thực thi lệnh (chương trình bắt đầu, tiêu thụ bộ nhớ, stdout / stderr sang shell)
  4. tái làm cho giả lập bởi các biến môi trường liên quan (ví dụ như $PS#, $PROMPT, vv)

Phần tôi muốn tìm ra nhiều nhất là tra cứu lệnh. Rõ ràng, $PATHđược sử dụng bởi một số chức năng nền và được phân tách bằng :/ ;như các dấu phân cách, vậy thì chuyện gì đã xảy ra? Chúng ta có sử dụng bảng băm (khóa: tên cơ sở của tệp, giá trị: tên thư mục tuyệt đối của tệp) để lưu trữ các tệp nhị phân trong các PATH đó hoặc một số hook khác không?

LƯU Ý: Ban đầu tôi nghĩ đó là bảng băm vì tôi có thể sử dụng [ -z hash [command] ]để kiểm tra xem một lệnh có sẵn trong env hiện tại không, nhưng khi tôi sử dụng, hash | grep pythontôi không nhận được gì từ đầu ra trong khi which pythonhoạt động như dự đoán. (Tôi nghĩ rằng cơ chế có thể là vỏ cụ thể, nhưng tôi muốn hiểu rõ hơn về nó.)

Câu trả lời:


11

Như bạn nghi ngờ, hành vi chính xác phụ thuộc vào vỏ, nhưng mức chức năng cơ bản được chỉ định bởi POSIX.

Tìm kiếm lệnh và thực thi ngôn ngữ lệnh shell tiêu chuẩn (mà hầu hết các shell thực hiện siêu bộ) có rất nhiều trường hợp, nhưng chúng ta chỉ quan tâm đến thời điểm này trong trường hợp PATHđược sử dụng. Trong trường hợp đó:

lệnh sẽ được tìm kiếm để sử dụng biến môi trường PATH như được mô tả trong Biến môi trường XBD

Nếu tìm kiếm thành công:

[...]

shell thực thi tiện ích trong một môi trường tiện ích riêng biệt với các hành động tương đương với việc gọi execl()hàm [...] với đối số đường dẫn được đặt thành tên đường dẫn do tìm kiếm.

Trong trường hợp không thành công, thực thi không thành công và mã thoát 127 được trả về với thông báo lỗi.

Hành vi này phù hợp với execvpchức năng, đặc biệt. Tất cả các exec*hàm chấp nhận tên tệp của một chương trình để chạy, một chuỗi các đối số (sẽ là argvcủa chương trình) và có lẽ là một tập hợp các biến môi trường. Đối với các phiên bản sử dụng PATHtra cứu, POSIX xác định rằng :

Đối số tập tin được sử dụng để xây dựng một danh sách chỉ rõ tên đường dẫn tập tin quá trình hình ảnh mới [...] tiền tố con đường cho tập tin này thu được bằng cách tìm kiếm các thư mục thông qua như biến môi trường PATH


Các hành vi của PATH được định nghĩa ở những nơi khác như:

Biến này sẽ biểu thị chuỗi các tiền tố đường dẫn mà các chức năng và tiện ích nhất định áp dụng khi tìm kiếm tệp thực thi chỉ được biết bởi tên tệp. Các tiền tố sẽ được phân tách bằng dấu hai chấm <(':'). Khi tiền tố có độ dài khác không được áp dụng cho tên tệp này, <slash> sẽ được chèn giữa tiền tố và tên tệp nếu tiền tố không kết thúc. Tiền tố có độ dài bằng không là một tính năng kế thừa cho biết thư mục làm việc hiện tại. Nó xuất hiện dưới dạng hai ký tự liền kề ("::"), dưới dạng <dấu hai chấm ban đầu trước phần còn lại của danh sách hoặc dưới dạng dấu <dấu> theo sau phần còn lại của danh sách. Một ứng dụng tuân thủ nghiêm ngặt sẽ sử dụng một tên đường dẫn thực tế (chẳng hạn như.) Để thể hiện thư mục làm việc hiện tại trong PATH.Danh sách sẽ được tìm kiếm từ đầu đến cuối, áp dụng tên tệp cho từng tiền tố, cho đến khi tìm thấy tệp thực thi có tên được chỉ định và quyền thực thi phù hợp . Nếu tên đường dẫn đang tìm kiếm chứa <dấu gạch chéo>, tìm kiếm thông qua tiền tố đường dẫn sẽ không được thực hiện. Nếu tên đường dẫn bắt đầu bằng <dấu gạch chéo>, đường dẫn đã chỉ định được giải quyết (xem Độ phân giải tên đường dẫn ). Nếu PATH không được đặt hoặc được đặt thành null, tìm kiếm đường dẫn được xác định theo thực hiện.

Đó là một chút dày đặc, vì vậy một bản tóm tắt:

  1. Nếu tên chương trình có /(dấu gạch chéo, U + 002F RẮN) trong đó, hãy coi nó như một đường dẫn theo cách thông thường và bỏ qua phần còn lại của quy trình này. Đối với shell, trường hợp này về mặt kỹ thuật không phát sinh (vì các quy tắc shell sẽ xử lý nó).
  2. Giá trị của PATHđược chia thành các phần tại mỗi dấu hai chấm, và sau đó mỗi thành phần được xử lý từ trái sang phải. Như một trường hợp đặc biệt (lịch sử), một thành phần trống của biến không trống được coi là .(thư mục hiện tại).
  3. Đối với mỗi thành phần, tên chương trình được gắn vào cuối cùng với sự nối /và sự tồn tại của tệp theo tên đó được kiểm tra và nếu tồn tại thì quyền cũng được kiểm tra (+ x) hợp lệ. Nếu một trong những kiểm tra đó thất bại, quá trình chuyển sang thành phần tiếp theo. Mặt khác, lệnh giải quyết theo đường dẫn này và tìm kiếm được thực hiện.
  4. Nếu bạn hết các thành phần, tìm kiếm thất bại.
  5. Nếu không có gì trong đó PATH, hoặc nó không tồn tại, hãy làm bất cứ điều gì bạn muốn.

Các shell thực sự sẽ có các lệnh dựng sẵn, được tìm thấy trước khi tra cứu này, và thường là bí danh và chức năng. Những người không tương tác với PATH. POSIX định nghĩa một số hành vi xung quanh những hành vi đó và vỏ của bạn có thể có nhiều hơn nữa.


Mặc dù có thể dựa vào exec*để thực hiện hầu hết việc này cho bạn, nhưng trình bao trong thực tế có thể tự thực hiện việc tra cứu này, đáng chú ý là cho mục đích lưu trữ, nhưng hành vi bộ đệm trống sẽ tương tự. Vỏ sò có vĩ độ khá rộng ở đây và có những hành vi khác nhau tinh tế trong các trường hợp góc.

Như bạn đã tìm thấy, Bash sử dụng bảng băm để ghi nhớ các đường dẫn đầy đủ của các lệnh mà nó đã thấy trước đó và bảng đó có thể được truy cập bằng hashhàm. Lần đầu tiên bạn chạy một lệnh, nó sẽ tìm kiếm và khi tìm thấy kết quả, nó sẽ được thêm vào bảng để không phải bận tâm tìm kiếm lần sau khi bạn thử.

Mặt khác, trong zsh, toàn bộ PATHthường được tìm kiếm khi vỏ bắt đầu. Một bảng tra cứu được chuẩn bị trước với tất cả các tên lệnh được phát hiện để việc tra cứu thời gian chạy thường không cần thiết (trừ khi một lệnh mới được thêm vào). Bạn có thể nhận thấy điều đó xảy ra khi bạn cố gắng hoàn thành một lệnh không tồn tại trước đó.

Các shell rất nhẹ, như dash, có xu hướng ủy thác càng nhiều hành vi càng tốt cho thư viện hệ thống và không bận tâm đến việc nhớ các đường dẫn lệnh trong quá khứ.


Cảm ơn tuyệt vời cho một lời giải thích chi tiết như vậy, điều này thực sự mang lại những hiểu biết sâu sắc. So sánh của bạn về PATHgiữa bashzshgiúp tôi giải quyết sự nhầm lẫn của tôi!
Xlee
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.