що zsh еквівалент експорту bash -f


24

Тому я почав використовувати zsh. Мені це подобається все добре. Це здається дуже крутим і гладким, і те, що поточний робочий каталог та фактичний командний рядок знаходяться в різних рядках, приємно, але в той же час, я помічаю, що це zshможе бути трохи повільніше bash, особливо, коли друкується текст на екран.

Що мені найбільше сподобалось, це те, що він zshбув "сумісним назад" з усіма функціями, які я визначив у своїй .bashrc.

Один захват, хоча. Всі функції прекрасно працюють, але я не можу зрозуміти, як працює система експорту.

У мене були .bashrcекспортовані деякі функції, щоб я міг їх використовувати в інших місцях, наприклад, у скриптах та зовнішніх програмах export -f.

У zsh, про експорт, здається, навіть не йдеться. Це автозавантаження? Ці дві речі однакові? Мені важко важко розібратися в цьому.


2
Це дуже давнє запитання, але я хочу сказати, що "поточний робочий каталог та фактичний командний рядок знаходяться в різних рядках" взагалі нічого спільного з zsh. Це залежить від того, як ви налаштуєте своє підказку, ось і все.
4ae1e1

Відповіді:


11

Змінні середовища, що містять функції, - це баш-хак. Zsh не має нічого подібного. Можна зробити щось подібне за допомогою декількох рядків коду. Змінні середовища містять рядки; старіші версії bash, перш ніж Shellshock були відкриті, зберігали код функції в змінній, ім'я якої - функція, і за значенням якої () {слідує код функції }. Ви можете використовувати наступний код для імпорту змінних за допомогою цього кодування та спробувати запустити їх з налаштуваннями, подібними до bash. Зверніть увагу, що zsh не може імітувати всі функції bash, все, що ви можете зробити, це трохи наблизитись (наприклад, $fooрозділити значення та розширити підстановку та зробити масиви на основі 0).

bash_function_preamble='
    emulate -LR ksh
'
for name in ${(k)parameters}; do
  [[ "-$parameters[name]-" = *-export-* ]] || continue
  [[ ${(P)name} = '() {'*'}' ]] || continue
  ((! $+builtins[$name])) || continue
  functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done

(Як зазначив Стіфан Шазелас , оригінальний відкривач Shellshock, більш рання версія цієї відповіді могла б виконати довільний код у цей момент, якщо визначення функції було неправильним. Ця версія не відповідає, але звичайно, як тільки ви виконаєте будь-яку команду, це може бути функція, імпортована з навколишнього середовища.)

Пост-Shellshock версії функцій кодування bash у середовищі, використовуючи недійсні імена змінних (наприклад BASH_FUNC_myfunc%%). Це ускладнює їх надійний аналіз, оскільки zsh не надає інтерфейс для вилучення таких імен змінних із середовища.

Я не рекомендую цього робити. Покладатися на експортовані функції в сценаріях - погана ідея: це створює невидиму залежність у вашому сценарії. Якщо ви коли-небудь запускаєте свій скрипт у середовищі, у якій немає вашої функції (на іншій машині, в роботі з хронічним процесом, після зміни файлів ініціалізації оболонок,…), ваш сценарій більше не працюватиме. Натомість збережіть усі свої функції в одному або декількох окремих файлах (щось на зразок ~/lib/shell/foo.sh) та запустіть сценарії, імпортуючи функції, які він використовує ( . ~/lib/shell/foo.sh). Таким чином, якщо ви модифікуєте foo.sh, ви можете легко шукати, які сценарії покладаються на нього. Якщо ви скопіюєте скрипт, ви зможете легко дізнатися, які допоміжні файли йому потрібні.

Zsh (і ksh до цього) робить це більш зручним, забезпечуючи спосіб автоматичного завантаження функцій у сценарії, де вони використовуються. Обмеження полягає в тому, що ви можете помістити лише одну функцію на файл. Оголосіть функцію автозавантаженою і введіть визначення функції у файл, ім'я якого - ім'я функції. Помістіть цей файл у каталог, вказаний у $fpath(який ви можете налаштувати за допомогою FPATHзмінної середовища). У своєму сценарії оголосіть функції автоматичного завантаження за допомогою autoload -U foo.

Крім того, zsh може компілювати сценарії, щоб заощадити час розбору. Зателефонуйте, zcompileщоб скласти сценарій. При цьому створюється файл із .zwcрозширенням. Якщо цей файл присутній, то autoloadзавантажуватиме складений файл замість вихідного коду. Ви можете використовувати zrecompileфункцію для (повторної) компіляції всіх визначень функцій у каталозі.


1
Смішно, як ваш код має таку ж вразливість оболонки bash(не підтверджує, що вміст змінної є лише визначенням функції та обробляє будь-яке ім'я змінної, як HTTP_HOSTабо LC_X). Гарна відповідь інакше.
Стефан Шазелас

@ StéphaneChazelas Якщо ви збираєтеся виконувати команди з функціями, імпортованими з навколишнього середовища, ви майже втратили. Але я оновив код імпорту, щоб не виконувати довільний код. Це не дуже корисно, оскільки пост-оболонка bash не кодує експортовані функції таким же чином.
Жил 'ТАК - перестань бути злим'

Тепер ви виправили еквівалент CVE-2014-6271, але все ще, ймовірно, піддаєтесь багатьом уразливості типу CVE-2014-6277 / 6278 ..., оскільки ви все ще виставляєте zsh парсер коду в будь-якій змінній в тому числі ті , які є потенційно під контролем зловмисників в деяких контекстах (як код в zsh -c 'functions[f]=$VAR' це аналізується , навіть якщо fфункція не викликається). Рішення полягає в тому, щоб враховувати лише ті змінні, чиє ім’я слідує зарезервованому шаблону на зразок тих $BASH_FUNC_x%%, але, як ви кажете, zshне має API, щоб їх перелічити чи отримати. perlНаприклад, вам потрібно буде зателефонувати .
Стефан Шазелас

7

Якщо ви помістите свою декларацію функції в .zshenv , ваша функція буде доступна зі сценарію без будь-яких зусиль.


Чому ти спростував мою відповідь? Будь ласка, поясніть.
рулети

Ще чекаю на відповідь і все ще працюю!
коти

Я щойно виявив цю відповідь, і це ідеальне рішення.
AFH

Я не спростовував цього. І TBH ОП запитувала про експорт матеріалів з .bashrc, що є поганою ідеєю, краще помістити його в сценарій, щоб ви не опинилися у величезному середовищі. Але ваше рішення є лише варіантом тієї самої поганої ідеї, вкладіть всі свої сценарії, .zshenvі це уповільнює кожну виклик zsh, аналізуючи багато коду, який ніколи не використовується. Далі це не те саме, що експортувати функцію, подібно до експортованої змінної, експортована функція доступна лише для дочірніх процесів. Тоді як речі, які ви вводите .zshenv, доступні для кожного zsh.
Метаморфний

Нарешті, якщо ви покладаєтесь на особистий код, який ви вводите у свій .zshenv, то всі ваші сценарії будуть абсолютно не портативними. Зазвичай сценарії можуть залежати один від одного, що добре, їх ви поширюєте разом. Але якщо вони залежать від наявності спеціальних функцій .zshenv, ніхто не захоче ними користуватися, або їм доведеться викликати спеціальну ZDOTDIR, не дозволяючи виконувати вашу власну .zshenv. Це був би біль.
Метаморфний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.