POSIX có đảm bảo đường dẫn đến bất kỳ tiện ích tiêu chuẩn nào không?


22

Từ C, cách dễ nhất để chạy một tiện ích tiêu chuẩn (ví dụ: ps) và không có gì khác?

POSIX có đảm bảo rằng, ví dụ, một tiêu chuẩn psđang ở /bin/pshoặc tôi nên đặt lại biến môi trường PATH thành những gì tôi nhận được confstr(_CS_PATH, pathbuf, n);và sau đó chạy tiện ích thông qua tìm kiếm PATH?


Ở phía sau đầu tôi, POSIX nói, đối với một số lệnh, trong số đó có ed (1) (rất quan trọng đối với mksh ), rằng, nếu chúng có sẵn, chúng cũng phải có thể truy cập được /bin, tức là /bin/edphải có thể sử dụng được nếu ed được cài đặt. Tôi không thể tìm thấy nó ngay bây giờ, nhưng tôi biết LSB phụ thuộc vào nó và tôi đã bảo vệ thành công bugreports bằng cách sử dụng nó như là lý do, vì vậy ít nhất nó phải đúng ở một số điểm. (Hoặc đó là một cái gì đó khác với POSuX và tôi đã đánh giá sai, nhưng phần còn lại là đúng.)
mirabilos

Câu trả lời:


33

Không, không, chủ yếu vì lý do đó nó không đòi hỏi hệ thống phải tuân theo mặc định , hoặc để tuân thủ chỉ tiêu chuẩn POSIX (để loại trừ bất kỳ tiêu chuẩn khác).

Chẳng hạn, Solaris (một hệ thống tuân thủ được chứng nhận) đã chọn khả năng tương thích ngược cho các tiện ích của nó /bin, điều này giải thích tại sao chúng hoạt động theo cách phức tạp và cung cấp các tiện ích tuân thủ POSIX ở các vị trí riêng biệt ( /usr/xpg4/bin, /usr/xpg6/bin... cho các phiên bản XPG khác nhau (hiện đã được hợp nhất theo tiêu chuẩn POSIX), những người thực sự là một phần của các thành phần tùy chọn trong Solaris).

Thậm chí shkhông được đảm bảo để được trong /bin. Trên Solaris, /bin/shtừng là vỏ Bourne (không tuân thủ POSIX) cho đến Solaris 10, trong khi bây giờ là ksh93 trong Solaris 11 (vẫn chưa hoàn toàn tuân thủ POSIX, nhưng thực tế còn hơn thế /usr/xpg4/bin/sh).

Từ C, bạn có thể sử dụng exec*p()và giả sử bạn đang ở trong môi trường POSIX (đặc biệt là về PATHbiến môi trường).

Bạn cũng có thể đặt PATHbiến môi trường

#define _POSIX_C_SOURCE=200809L /* before any #include */
...
confstr(_CS_PATH, buf, sizeof(buf)); /* maybe append the original
                                      * PATH if need be */
setenv("PATH", buf, 1);
exec*p("ps"...);

Hoặc bạn có thể xác định tại thời điểm xây dựng đường dẫn của các tiện ích POSIX mà bạn muốn chạy (lưu ý rằng trên một số hệ thống như GNU, bạn cần nhiều bước hơn như đặt POSIXLY_CORRECTbiến để đảm bảo tuân thủ).

Bạn cũng có thể thử những thứ như:

execlp("sh", "sh", "-c", "PATH=`getconf PATH`${PATH+:$PATH};export PATH;"
                         "unset IFS;shift \"$1\";"
                         "exec ${1+\"$@\"}", "2", "1", "ps", "-A"...);

Với hy vọng rằng có một shtrong $PATH, mà nó là Bourne-như thế nào, mà đó cũng là một getconfvà rằng đó là một cho phiên bản của POSIX bạn trong tâm đang.


Vậy bạn làm gì cho #!?
Joshua

13
@Joshua: Bạn cầu nguyện rằng nó /usr/bin/envtồn tại và chủ yếu tuân thủ POSIX.
Kevin

3
@Kevin hoặc bạn làm quen với những điều kỳ quặc của palaeo-unix của bạn và điều chỉnh #! dòng để sử dụng đúng đường dẫn.
cas

3
@Kevin: Số /usr/bin/envlà một hack thậm chí ít di động (trong thực tế) hơn /bin/sh. Mỗi POSIX, cách cầm tay để viết một kịch bản shell là không có #!gì cả . Nếu một tệp có thể thực thi được ENOEXEC( nhưng không phải là nhị phân hợp lệ), execvplà thực thi nó thông qua trình bao tiêu chuẩn. :-) Tất nhiên trong thực tế đây là một ý tưởng tồi và bạn chỉ nên sử dụng #!/bin/sh.
R ..

2
@GeoffNixon, phần mà bạn đang tham khảo là một giải pháp thay thế khi bạn không, không thể hoặc không muốn sử dụng _POSIX_C_SOURCE. Nó thực hiện cài đặt $PATHtừ vỏ thay vì từ C.
Stéphane Chazelas

3

Trên thực tế, tôi sẽ trả lời phần lớn là . POSIX không đảm bảo:

  1. Đó có một đường dẫn tuyệt đối một với phiên bản tiêu chuẩn tuân thủ của mỗi tiện ích nhất định,
  2. Và, rằng bạn phải có thể tìm thấy đường dẫn tuyệt đối này và có thể thực thi tiện ích này.

Mặc dù không nhất thiết phải đảm bảo rằng mỗi tiện ích sẽ nằm trong một thư mục cụ thể trên tất cả các hệ thống ( /bin/ps), nhưng nó luôn được đảm bảo thể tìm thấy trong PATH mặc định của hệ thống, dưới dạng tệp thực thi.

Thật vậy, cách duy nhất tiêu chuẩn quy định để làm điều này trong tiêu chuẩn là (C) qua unistd.h's _CS_PATH, hoặc trong vỏ, thông qua một sự kết hợp của commandgetconftiện ích, tức là PATH="$(command -p getconf PATH)" command -v psluôn luôn phải trả lại đường dẫn tuyệt đối duy nhất của các POSIX-compliant psđược cung cấp trên một hệ thống cụ thể. Đó là, mặc dù được xác định theo thực thi , những đường dẫn nào được bao gồm trong biến PATH mặc định của hệ thống, những sử dụng này phải luôn có sẵn, duy nhất và tuân thủ, trong một trong những đường dẫn được chỉ định trong đó.

Xem: < unistd.h >, lệnh .


Nhưng đối với sh, có một vấn đề gà và trứng. Điều đó PATH=$(command -p getconf PATH)sẽ chỉ hoạt động từ vỏ POSIX trong môi trường POSIX. POSIX không chỉ định cách bạn vào môi trường đó, chỉ là nó được ghi lại. Ví dụ, trên Solaris, bạn có một /usr/xpg4/bin/getconfvà một /usr/xpg6/bin/getconftrong đó sẽ trả về giá trị khác nhau cho _CS_PATHcho hai phiên bản khác nhau của tiêu chuẩn và không phải /usr/xpg4/binvà cũng không /usr/xpg6/binđược tính vào giá trị mặc định của $PATH. Có một /usr/bin/getconfIIRC cung cấp cho bạn sự phù hợp XPG4.
Stéphane Chazelas

Điều đó có đúng với ngay cả đối với các phiên bản Solaris 11+ (được chứng nhận UNIX 03+) không? Tôi đã luôn luôn đọc `` `Các ứng dụng ... nên được xác định bằng cách thẩm vấn PATH được trả về bởi getconf PATH, đảm bảo rằng tên đường dẫn được trả về là một tên đường dẫn tuyệt đối chứ không phải là một vỏ được tích hợp. Ví dụ: để xác định vị trí của tiện ích sh tiêu chuẩn: lệnh -v sh Trên một số triển khai, điều này có thể trả về: / usr / xpg4 / bin / sh `` `có nghĩa đây phải là một mục nhập theo chuẩn POSIX shtừ bất kỳ shell mặc định nào .
Geoff Nixon

1
Không có gì trong POSIX nói rằng cần có một getconflệnh trong mặc định $PATHcủa một hệ thống nhất định. Chẳng hạn, có được môi trường POSIX có thể liên quan đến việc bắt đầu một lớp mô phỏng, mà không có điều gì bạn sẽ không chạy bất kỳ lệnh nào giống Unix (ví dụ như Windows). Khi bạn ở trong một môi trường tuân thủ, getconf PATH bạn sẽ có $PATHđược các tiện ích tuân thủ, nhưng nếu bạn ở trong môi trường POSIX, điều đó có lẽ đã xảy ra. Lưu ý rằng getconf pscó thể trở lại ps. Có psnội dung được cho phép.
Stéphane Chazelas
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.