Чому bash навіть розбирає / запускає речі, поміщені в змінну середовища?


9

Shellshock помилка в Баш працює шляхом змінних оточення. Чесно кажучи, мене здивувало те, що є така особливість, як:

"передача визначень функції через env vars"

Тому це питання, хоча, можливо, не ідеально сформульоване - це попросити приклад чи випадок, у якому потрібно було б мати цю особливість?

Бонус. Чи мають інші функції оболонки zsh, dash тощо?


Він використовує env vars для передачі визначень функцій. Що ви маєте на увазі під "Чому він не просто підтримує змінні середовища доступними / доступними?" ?
Антон

@Anthon Дякую за коментар Можливо, я повинен бути більш чітким і перефразовувати. З якої причини необхідно мати можливість передавати визначення функцій через env vars?
humanityANDpeace

1
Я не впевнений на 100%, але думаю, що, наприклад, GNU parallelотримує визначення функцій, якщо вони викликають кілька екземплярів bash. Якщо це не так, потрібно було б записати ті у файл, який читає кожен викликаний екземпляр, і тоді вам доведеться вирішувати проблеми, наприклад, коли цей файл можна видалити.
Антон

2
ця тема має певну історію. Експортовані функції, однак, божевільні . якщо ви хочете, щоб нова оболонка успадкувала старі виконувані команди оболонки, ви .dotстворите той самий файл, що і старий. ось як це зроблено - і це має сенс - або ви подаєте нову оболонку файлу як вхідний файл, коли execing. як тільки воно прочитане, як тільки файл буде кешований ядром все одно.
mikeserv

@mikeserv Чи правильно я розумію, що значна частина оболонки пов'язана з цією особливістю, яка все одно не так важлива?
humanityANDpeace

Відповіді:


4

Коли скрипт викликає інший сценарій, змінні батьківського сценарію можуть бути експортовані, а потім вони будуть видимі в дочірньому сценарії. Експорт функцій є очевидним узагальненням: експортуйте функцію від батьків, зробіть її видимою у дитини.

Навколишнє середовище - єдиний зручний спосіб, коли процес може передавати довільні дані своїм дітям. Дані повинні бути об'єднані в рядки, що не містять нульових байтів, що не представляє труднощів для функцій оболонки. Є й інші потенційні методи, такі як блоки спільної пам'яті або тимчасові файли, що передаються через дескриптори файлів, але вони можуть спричинити проблеми з проміжними програмами, які не знають, що з ними робити, або закриють їх. Програми очікують працювати в середовищі, яке містить змінні, про які вони не знають і не цікавляться, тому вони не будуть перезаписувати чи стирати їх.

Вибір використання назви функції як імені змінної середовища є дивним. По-перше, це означає, що експортована змінна стикається з функцією, що експортується з тим самим ім'ям.

Експортовані функції - це стара функція. Функції були додані в оболонку Bourne в SVR2 , а експортні функції в оболонці Версії 8 випущені в тому ж році (1984). У цій оболонці змінні та функції використовували один і той же простір імен. Я не знаю, як працював експорт функцій. Heirloom оболонки заснована на варіанті Bourne , який має функції , але не експортувати їх.

ATT ksh нібито підтримує функції експорту, але дивлячись на джерело або граючи з ним, я не можу побачити, що він робить, як ksh93u.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Клони відкритого домену Ksh (pdksh, mksh), dash та zsh не підтримують функції експорту.


1
Дякую тобі! Отже, без експорту функцій функціональна функція втрачається, але є така оболонка, як тире, zsh та pdksh тощо, яким не вистачає цієї функціональності, чи читаю я це правильно?
humanityANDpeace

Але коли я експортую функцію в bash, вона переходить в змінну на зразок BASH_FUNC_f%%=() { echo hi }. Чому bash аналізує інші змінні середовища? Чому він би навіть розбирався, BASH_FUNC_g%%коли я лише дзвоню f? (Судячи з усього, попередній обстріл, змінна середовища була щойно викликана fабо g- але мені все ще цікаво, чому gбуло б розібрано, якщо я ніколи не дзвоню gв моєму сценарії)
Metamorphic

@Met Треба переглянути всі змінні середовища, щоб визначити, які з них є визначеннями функцій. Це могло б запам'ятати цей факт і уникнути розбору коду функції до першого разу, коли це буде потрібно, але це буде додатковою складністю для дуже невеликого посилення. Простіше мати лише один тип функції, а не дві ("нормальна функція" та "функція із змінної середовища, яка потребує трохи розбору").
Жил "ТАК - перестань бути злим"

Не чисто. Я припускаю, що очевидною справою було б, коли я запускаю щось, що називається f, (1) перевірка функції оболонки під назвою f, (2) перевірка наявності змінної середовища, що називається f, і спроба її розбору, (3) перевірка кожен PATHкомпонент для виконавчого файлу називається f. Як розбір кожної змінної середовища, як код оболонки, при запуску оболонки може здатися менш складним дизайном?
Метаморфний

@Metamorphic Ви пропонуєте додати ще один крок, який повинен бути виконаний у кожній команді. Вам також доведеться додати ще один крок при визначенні чи визначенні функцій (після цього unset -f foo, bash більше не повинен шукати визначення функції fooв оточенні), коли перераховувати функції (як ви обробляєте declare -fінше, ніж читати всі змінні середовища?) , і що б я не думав. Ваш дизайн здається простішим лише тому, що ви залишили його більшу частину. На відміну від цього, робити все при запуску - це єдиний фрагмент коду, і після цього все просто працює.
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.