Почему POSIX требует, чтобы определенные встроенные модули оболочки имели внешнюю реализацию?

19

Из этого вопроса о том, является ли printf встроенным для yash , следует ответ, который цитирует стандарт POSIX .

Ответ указывает на то, что последовательность поиска POSIX должна найти внешнюю реализацию желаемой команды, а затем, если оболочка реализовала ее как встроенную, запустить встроенную. (Для встроенных модулей, которые не являются специальными встроенными модулями .)

Почему POSIX имеет это требование для существования внешней реализации, прежде чем разрешить запуск внутренней реализации?

Это кажется ... произвольным, поэтому мне любопытно.

studog
источник
Я считаю, что это способ включить / отключить встроенные функции, если это необходимо / требуется.
Исаак
2
Отключить встроенную, удалив внешнюю реализацию? Сейчас нет доступных команд с именем printf.
Стадог
@studog, поэтому создайте пустой файл с тем же именем, что и встроенный, включите бит выполнения и поместите его в каталог в вашей переменной PATH. : P
Wildcard
@Wildcard Строго совместимая оболочка будет видеть имя при поиске PATHи затем вызывать встроенную утилиту, а не внешний скрипт. Что если вы захотите вызвать внешний скрипт на вашем пути? Хм ... Кажется, это требует таблицы с описанием различных возможностей. Существует одна здесь , но это не имеет смысла для меня.
Кусалананда
@Kusalananda, твое первое предложение, это была моя точка зрения. Следовательно, почему я сказал создать пустой файл.
Wildcard

Ответы:

15

Это правило «как будто».

Проще говоря: поведение оболочки в том виде, в каком ее видят пользователи, не должно меняться, если реализация решит сделать стандартную внешнюю команду также доступной в качестве встроенной оболочки.

Контраст, который я показал на /unix//a/496291/5132, между поведением (с одной стороны) оболочек PD Korn, MirBSD Korn и Heirloom Bourne; (с другой стороны) оболочки Z, 93 Korn, Bourne Again и Debian Almquist; и (на захватной руке) оболочка Ватанабэ подчеркивает это.

Для оболочек, которые не имеют printfвстроенной функции, удаление /usr/binиз PATHвызывает вызов printfпрекращения работы. Поведение, соответствующее POSIX, демонстрируемое оболочкой Watanabe в ее режиме, приводит к тому же результату. Поведение оболочки, имеющей printfвстроенную функцию, выглядит так, как будто она вызывает внешнюю команду.

Принимая во внимание, что поведение всех несовместимых оболочек не изменяется, если /usr/binудаляется из PATH, и они не ведут себя так, как если бы они вызывали внешнюю команду.

Стандарт пытается гарантировать вам, что оболочки могут встраивать всевозможные обычно внешние команды (или реализовывать их как свои собственные функции оболочки), и вы по-прежнему будете вести себя так же, как и встроенные. с внешними командами, если вы настраиваете, PATHчтобы остановить команды от поиска. PATHостается вашим инструментом для выбора и управления, какие команды вы можете вызвать.

(Как объяснено на /unix//a/448799/5132 , несколько лет назад люди выбирали индивидуальность своего Unix, изменяя то, что было включено PATH.)

Можно предположить, что выполнение команды всегда работает независимо от того, где она может быть найдена, на PATH самом деле является целью встроить обычно внешние команды. (Именно поэтому мой набор инструментов nosh только что получил встроенную printenvкоманду в версии 1.38. На самом деле это не оболочка.)

Но стандарт дает вам гарантию того, что для обычных внешних команд, которые не включены в оболочку , вы увидите то же поведение, что и в PATHдругих не-оболочечных программах, вызывающих execvpe()функцию, и оболочка не сможет волшебным образом запускать (очевидно) обычные внешние команды, которые другие программы не могут найти с тем же PATH. Все работает самосогласованно с точки зрения пользователя и PATHявляется инструментом для управления его работой.

дальнейшее чтение

JdeBP
источник
13

Это довольно абсурдно, и поэтому ни одна оболочка не реализует его в режиме по умолчанию.

Обоснование стандарта и его иллюстрирующий пример предполагают, что это была неудачная попытка иметь регулярную встроенную функцию, связанную с путем, и позволить пользователю переопределить ее, представив свой собственный двоичный файл перед ним PATH(например, printfвстроенную функцию, связанную с /usr/bin/printfможет быть отменено /foo/bin/printfвнешней командой путем установки PATH=/foo/bin:$PATH).

Однако стандарт не требовал этого, но что-то совершенно иное (а также бесполезное и неожиданное).

Вы можете прочитать больше об этом в этом сообщении об ошибке . Цитата из окончательного принятого текста :

Многие существующие реализации выполняют обычные встроенные функции, не выполняя поиск по PATH. Такое поведение не соответствует нормативному тексту и не позволяет авторам сценариев переопределять обычные встроенные утилиты через специально созданный PATH. Кроме того, обоснование объясняет, что цель состоит в том, чтобы позволить авторам переопределить встроенные модули, изменив PATH, но это не то, что говорится в нормативном тексте .

FWIW, я не думаю, что есть какая-либо оболочка, реализующая пересмотренные требования из принятого текста, либо.

mosvy
источник
Смотрите также обсуждение на article.gmane.org/gmane.comp.standards.posix.austin.general/… (и там было несколько других).
Стефан Шазелас
Также github.com/att/ast/issues/370 (длинный)
Стефан Шазелас
Нет (например, встроенная функция printf, связанная с / usr / bin / printf, может быть переопределена внешней командой / foo / bin / printf путем установки PATH = / foo / bin: $ PATH). это неверно. Наличие / обоих / любого из /usr/bin/printfили /foo/bin/printfв PATH активирует встроенный printf. Единственное, что printfбудет делать отсутствующий (в PATH) внешний - это отключить встроенную функцию. (По букве спецификации).
Исаак