Чи гарантує POSIX шлях до будь-яких стандартних утиліт?


22

З C, який найпростіший спосіб запустити стандартну утиліту (наприклад, ps) та жодну іншу?

Чи має POSIX гарантії , що, наприклад, стандарт psв /bin/psабо я повинен скинути змінну оточення PATH , щоб отримати те , що я з confstr(_CS_PATH, pathbuf, n);і потім запустити програму через PATH-пошуку?


Я маю на задній частині голови про те, що POSIX для ряду команд, серед них ed (1) (що важливо для mksh ), говорить , що, якщо вони є, вони також мають бути доступними /bin, тобто /bin/edповинні бути корисними якщо редактор встановлений Я зараз не можу його знайти, але я знаю, що від цього залежить LSB, і я успішно захищав бугрепорти, використовуючи це як обґрунтування, тому це, мабуть, було правдою в якийсь момент. (Або це було щось інше, ніж POSuX, і я згадую, але все інше правда.)
mirabilos

Відповіді:


33

Ні, це відбувається, головним чином, з тієї причини, що він не вимагає, щоб системи за замовчуванням відповідали системам або відповідали лише стандарту POSIX (виключаючи будь-який інший стандарт).

Наприклад, Solaris (сертифікована сумісна система) обрала зворотну сумісність для своїх утиліт, в /binякій пояснюється, чому вони поводяться таємно, та надає утиліти, сумісні з POSIX, в окремих місцях ( /usr/xpg4/bin, /usr/xpg6/bin... для різних версій XPG (тепер об'єднана) в стандарт POSIX), які фактично є частиною необов'язкових компонентів у Solaris).

Навіть shне гарантовано буде в /bin. На Solaris, який /bin/shраніше був оболонкою Bourne (тому не сумісний з POSIX) до Solaris 10, в даний час це ksh93 в Solaris 11 (все ще не повністю POSIX сумісний, але на практиці більше, ніж /usr/xpg4/bin/sh).

З C ви можете використовувати exec*p()та припускати, що ви перебуваєте в середовищі POSIX (зокрема, щодо PATHзмінної середовища).

Ви також можете встановити PATHзмінну середовища

#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"...);

Або ви можете визначити в час збирання шлях утиліт POSIX, які ви хочете запустити (маючи на увазі, що для деяких систем, таких як GNU, вам потрібно більше кроків, як встановлення POSIXLY_CORRECTзмінної для забезпечення відповідності).

Ви також можете спробувати такі речі, як:

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

У надії , що є shв $PATH, що це Bourne-подібний, що є також getconfі що це один для версії POSIX ви зацікавлені в.


То що ви робите для # !?
Джошуа

13
@Joshua: Ви молитесь про те, що /usr/bin/envіснує і здебільшого підтримує POSIX.
Кевін

3
@Kevin або ти ознайомишся з примхами свого палео-унікса та відрегулюєш #! рядок, щоб використовувати правильний шлях.
cas

3
@Kevin: Ні /usr/bin/env- це навіть менш портативний (на практиці) хак, ніж /bin/sh. За POSIX, портативний спосіб написати скрипт НЕ з не #!зовсім . Якщо файл виконується, але ENOEXEC(не є дійсним бінарним файлом), execvpслід виконати його за допомогою стандартної оболонки. :-) Звичайно, на практиці це погана ідея, і вам слід просто скористатися #!/bin/sh.
Р ..

2
@GeoffNixon, ця частина, яку ви пропонуєте, є альтернативою, коли ви не можете, не можете чи не хочете використовувати _POSIX_C_SOURCE. Це робить установку $PATHз оболонки замість C.
Стефан Шазелас

3

Власне, я б значною мірою відповів « так» . POSIX гарантує:

  1. Тобто це абсолютний шлях а відповідні стандарти версії кожної зазначеної утиліти,
  2. І, що ви повинні вміти знайти цей абсолютний шлях і вміти виконувати цю утиліту.

Хоча не обов'язково гарантується, що кожна утиліта буде знаходитись у певному каталозі для всіх систем ( /bin/ps), вона завжди гарантує, що її можна буде знайти в системному PATH за замовчуванням, як виконуваний файл.

Дійсно, єдиний стандартний спосіб зробити це в стандарті (в C) через unistd.h's _CS_PATH, або в оболонці, за допомогою комбінації commandта getconfутиліт, тобто PATH="$(command -p getconf PATH)" command -v psзавжди повинен повертати унікальний абсолютний шлях, сумісний з POSIX psпоставляється в певній системі. Тобто, хоча це визначено реалізацією, які шляхи включені до системної змінної PATH за замовчуванням, ці утиліти повинні бути завжди доступними, унікальними та сумісними в одному з вказаних у ній шляхів.

Див .: < unistd.h >, команда .


Але для ш, є проблема з куркою та яйцями. Це PATH=$(command -p getconf PATH)буде працювати тільки з оболонки POSIX в середовищі POSIX. POSIX не вказує, як ви потрапляєте в це середовище, лише щоб це було задокументовано. Так , наприклад, на Solaris, ви їсте /usr/xpg4/bin/getconfі /usr/xpg6/bin/getconfякий буде повертати різні значення _CS_PATHдля двох різних версій стандарту і ні /usr/xpg4/binні /usr/xpg6/binв значенні за замовчуванням $PATH. Існує /usr/bin/getconfIIRC, який відповідає XPG4.
Стефан Шазелас

Це правда навіть для версій Solaris 11+ (сертифікована UNIX 03+)? Я завжди читав `` `Програми ... слід визначати шляхом допиту PATH, повернутого getconf PATH, гарантуючи, що повернене ім'я шляху є абсолютним іменем шляху, а не вбудованою оболонкою. Наприклад, для визначення розташування стандартної утиліти sh: команда -v sh У деяких реалізаціях це може повернутися: / usr / xpg4 / bin / sh `` `, щоб означати, що це повинно бути записом до POSIX-сумісного shз будь-якої оболонки за замовчуванням .
Джефф Ніксон

1
У POSIX немає нічого, що говорить про те, що повинна бути getconfкоманда за замовчуванням $PATHдля даної системи. Наприклад, отримання середовища POSIX може спричинити запуск рівня емуляції, без якого ви взагалі не запускаєте жодної команди, подібної Unix (наприклад, Windows). Опинившись у сумісному середовищі, getconf PATH ви отримаєте $PATHдоступ до сумісних утиліт, але якщо ви опинилися в середовищі POSIX, це, мабуть, вже було так. Зверніть увагу, що getconf psможе повернутися ps. Наявність psвбудованої команди допускається.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.