POSIX гарантирует пути к любым стандартным утилитам?

22

Из C, какой самый простой способ запустить стандартную утилиту (например, ps) и ничего другого?

Имеет ли POSIX гарантии , что, например, стандарт psв /bin/psили я должен сбросить переменную окружения PATH , чтобы получить то , что я с confstr(_CS_PATH, pathbuf, n);и затем запустить программу через PATH-поиска?

PSkocik
источник
В глубине моей головы POSIX говорит, что для ряда команд, в том числе ed (1) (что важно для mksh ), что, если они доступны, они также должны быть доступны в /bin, т. Е./bin/ed Должны использоваться если 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, в то время как в Solaris 11 она теперь ksh93 (все еще не полностью 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
@ Иисус Навин: Ты молишься о том, что /usr/bin/envсуществует и в основном соответствует POSIX.
Кевин
3
@Kevin или вы познакомитесь с причудами своего палео-юникса и отрегулируете #! линия, чтобы использовать правильный путь.
КАС
3
@Kevin: Нет. /usr/bin/envЭто еще менее переносимый (на практике) взломать, чем /bin/sh. За POSIX, портативный способ написать скрипт не с не #!совсем . Если файл является исполняемым, но ENOEXEC(не допустимым двоичным файлом ), execvpон должен выполняться через стандартную оболочку. :-) Конечно, на практике это плохая идея, и вы должны просто использовать #!/bin/sh.
R ..
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 >, команда .

Джефф Никсон
источник
Но для sh, есть проблема курицы и яйца. Это PATH=$(command -p getconf PATH)будет работать только из оболочки POSIX в среде POSIX. POSIX не определяет, как вы попадаете в эту среду, он просто документируется. Например, в Solaris у вас есть a /usr/xpg4/bin/getconfи a, /usr/xpg6/bin/getconfкоторые возвращали бы разные значения для _CS_PATHдвух разных версий стандарта, и ни то, /usr/xpg4/binни другое не /usr/xpg6/binимеют значения по умолчанию $PATH. Существует, /usr/bin/getconfчто IIRC дает вам соответствие 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встроенной команды допускается.
Стефан Шазелас