Поведінка "eval" під "set -e" в умовному вираженні


10

Розглянемо команди

eval false || echo ok
echo also ok

Зазвичай, ми очікуємо, що ця програма виконає falseутиліту, і, оскільки статус виходу є нульовим, потім виконати echo okі echo also ok.

У всіх POSIX-подібних оболонок , які я використовую ( ksh93, zsh, bash, dash, OpenBSD ksh, і yash), це те , що відбувається, але все стає цікаво , якщо ми включаємо set -e.

Якщо set -eдіє, OpenBSD shі kshоболонки (обидва отримані з pdksh) припиняють сценарій при виконанні eval. Жодна інша оболонка цього не робить.

POSIX говорить, що помилка в спеціальній вбудованій утиліті (наприклад, eval) повинна призвести до припинення неінтерактивної оболонки. Я не зовсім впевнений, чи є виконання false"помилкою" (якби воно було, воно було б незалежним від set -eактивності).

Шлях подолання цього, здається, полягає в тому, щоб помістити evalв під оболонку,

( eval false ) || echo ok
echo also ok

Питання полягає в тому, чи очікується, що мені доведеться це робити в правильному сценарії оболонки POSIX, чи це помилка в оболонці OpenBSD? Крім того, що означає "помилка" у тексті POSIX, пов'язаному вище?


Додатковий біт інформації: оболонки OpenBSD виконуватимуть echo okяк з командою, так і без set -e неї

eval ! true || echo ok

Мій оригінальний код виглядав так

set -e
if eval "$string"; then
    echo ok
else
    echo not ok
fi

який не виводиться not okз string=falseвикористанням оболонок OpenBSD (він припиняється), і я не був впевнений, що це було з дизайну, помилки чи нерозуміння чи чогось іншого.


eval falseгенерує ненульовий статус, тому я би сподівався set -eприпинити сценарій у той момент. У разі ! set -eне застосовується, оскільки !оператор прямо перевіряє стан виходу.
fcbsd

@fcbsd Чи очікуєте ви eval falseскасувати скрипт, навіть якщо він є частиною списку AND-OR або умовною заявою? Я б не став.
Кусалаланда

Я не впевнений, чи set -eвстановлено це, якщо це правильна поведінка ... Я погоджуюся, що в умовному висловлюванні має сенс не закінчуватися.
fcbsd

зігравши ще трохи, з sh на CentOS 7 - я б сказав, що призначена поведінка для ksh / sh OpenBSD при використанні, set -eтак що `() 'є відповіддю.
fcbsd

Відповіді:


4

Те, що жодна інша оболонка не потребує такого вирішення, є яскравим свідченням того, що це помилка в OpenBSD ksh. Насправді, ksh93 не видає такої проблеми.

Що ||в командному рядку є, повинно уникати виходу оболонки, викликаного зворотним кодом 1 на лівій стороні від неї.

Помилка спеціального вбудованого пристрою повинна викликати вихід неінтерактивної оболонки відповідно до POSIX, але це не завжди відповідає дійсності. Спроба continueвийти з циклу є помилкою і continueє вбудованою. Але більшість снарядів не виходить на:

continue 3

Вбудований, який видає явну помилку, але не виходить.

Отже, вихід на falseпороджується set -eумовою, а не вбудованою характеристикою команди ( evalв даному випадку).

Точні умови, на які потрібно set -eвийти, є ще більш нечіткими в POSIX.


Це повторює відповідь, що я вийшов із списку розсилки OpenBSD, але з більшою кількістю слів, дякую! Я розберу належний звіт про помилку, і якщо нічого не станеться, я сам перегляну вихідний код.
Кусалаланда

4

[Вибачте, якщо це не справжня відповідь, я її оновлю, коли обійдуся нею]

Я ознайомився з вихідним кодом, і мої висновки:

1) Це помилка / обмеження, за цим не стоїть нічого філософського.

2) "Виправлення" для нього з портативної вилки ksh ( mksh) OpenBSD є дуже поганою, лише погіршує ситуацію, не поправляючи її:

Нова помилка, відмінна від усіх інших оболонок:

mksh -ec 'eval "false; echo yup"'
yup

bash -ec 'eval "false; echo yup"'
(nothing)

Все ще не зафіксовано:

mksh -ec 'eval "set -e; false" || echo yup'
(nothing)

bash -ec 'eval "set -e; false" || echo yup'
yup

Ви можете замінити bashвище dash, zsh, yash, ksh93і т.д.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.