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
và
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 execvp
chứ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à argv
củ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 PATH
tra 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:
- 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ó).
- 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).
- Đố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.
- Nếu bạn hết các thành phần, tìm kiếm thất bại.
- 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 hash
hà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ộ PATH
thườ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ứ.
PATH
giữabash
vàzsh
giúp tôi giải quyết sự nhầm lẫn của tôi!