Чому POSIX вимагає певних вбудованих оболонок для зовнішньої реалізації?


19

З цього питання про те, чи є printf вбудованим для yash , виходить ця відповідь, яка цитує стандарт POSIX .

У відповіді вказується, що послідовність пошуку POSIX полягає у пошуку зовнішньої реалізації потрібної команди, а потім, якщо оболонка реалізувала її як вбудовану, запустіть вбудовану. (Для вбудованих модулів, які не є спеціальними вбудованими .)

Чому POSIX має цю вимогу щодо зовнішньої реалізації, перш ніж дозволяти запускати внутрішню реалізацію?

Здається ... довільно, тому мені цікаво.


Я вважаю, що це спосіб увімкнути / вимкнути вбудовані файли за бажанням / необхідності.
Ісаак

2
Вимкнення вбудованого модуля шляхом видалення зовнішньої реалізації? Зараз немає printfдоступних команд імені .
студог

@studog, тому створіть порожній файл з тим самим іменем, що і вбудований, увімкніть біт виконання і покладіть його в каталог у вашому PATH. : P
Wildcard

@Wildcard Строго сумісна оболонка побачила б це ім'я під час пошуку, PATHа потім викликає вбудовану утиліту, а не зовнішній скрипт. Що робити, якщо ви хочете викликати зовнішній скрипт на своєму шляху? Хм ... Це, здається, вимагає таблиці, що описує різні можливості. Існує одна тут , але це не має сенсу для мене.
Kusalananda

@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є інструментом для контролю того, як він працює.

Подальше читання


13

Це досить абсурдно, і тому жодна оболонка не реалізує його в режимі за замовчуванням.

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

Однак стандарт не вимагав цього, а щось зовсім інше (а також марне і несподіване).

Детальніше про це ви можете прочитати у цьому звіті про помилки . Цитування з остаточного прийнятого тексту :

Багато існуючих реалізацій виконують звичайну вбудовану програму, не здійснюючи пошук PATH. Така поведінка не відповідає нормативному тексту, і це не дозволяє авторам сценаріїв перекривати звичайні вбудовані утиліти через спеціально створений PATH. Крім того, обґрунтування пояснює, що намір полягає в тому, щоб автори могли переосмислити вбудовані модулі, змінивши PATH, але це не те, що йдеться в нормативному тексті .

FWIW, я не думаю, що немає жодної оболонки, яка реалізує переглянуті вимоги з прийнятого тексту.


Дивіться також дискусію на Article.gmane.org/gmane.comp.standards.posix.austin.general/… (і було декілька інших).
Стефан Шазелас

Також github.com/att/ast/isissue/370 (тривалий)
Stéphane Chazelas

Ні, (наприклад, вбудований printf, пов'язаний з / usr / bin / printf, може бути замінений зовнішньою командою / foo / bin / printf, встановивши PATH = / foo / bin: $ PATH). , це неправильно. Існування або / і / будь-якого з, /usr/bin/printfабо /foo/bin/printfв PATH активує вбудований printf. Єдине, що printfзробить зниклий (у PATH) зовнішній - це відключити вбудований. (За листом спец.).
Ісаак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.