Використання set -u не працює, як очікувалося


12

Я вивчаю, як ефективно використовувати різні setпараметри в моєму сценарії, і натрапив на set -uте, що, здається, є ідеальним для виходу зі свого сценарію, якщо змінна не встановлена ​​належним чином (наприклад, видалення користувачів). За даними сторінки людини , set -uчи set -eробить наступне ...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

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

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

Я очікую, що сценарій відобразить 0 і "Це працює" , а потім не вдасться, як ${testing2}не встановлено.

Натомість мені відображається 0 і "Це працює" , далі 0, а потім 0 Це не повинно з'являтися

Хтось може надати якісь знання? Дякую.


1
Тож подальший процес ... чи є спосіб зробити встановлення змінної на null рядок незаконним / підняти помилку? Я здогадуюсь, ні.
Люк Девіс

Відповіді:


10

Від "man Bash":

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

Коли ви це робите, testing2=ви встановлюєте змінну до нульового рядка.

Змініть це на unset testing2і повторіть спробу.


У set -eцьому випадку не допомагає, оскільки у призначенні ніколи не є вихідний код 1. Спробуйте це переконатися, що остання виконана команда (призначення) має вихідний код 0, або прочитайте це запитання :

$ false; a=""; echo $?
0

І я також вважаю, що використання set -e - це більше проблема, ніж рішення.

Що може отримати помилку при використанні невстановлених змінних set -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

Виведе:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable

3

testing2=встановлює testing2змінну в порожній рядок; змінна фактично встановлена .

Однак якщо ви працювали echo $testing99в інтерактивній оболонці Bash (без налаштування errexit, тобто set -e), ви отримаєте помилку:

bash: testing99: unbound variable

Убік

Під час тестування сценаріїв лише зараз я виявив, що інтерактивна оболонка не завжди виходить при спробі розширення змінної, яка не була встановлена, поки неінтерактивна оболонка (запуск сценарію оболонки) завжди залишається . Відповідно до чоловічої сторінки POSIX для set:

-u Оболонка повинна написати повідомлення на стандартну помилку, коли вона намагається розгорнути змінну, яка не встановлена, і негайно вийти. Інтерактивна оболонка не повинна виходити.

Інтерактивна оболонка Bash не вийде, якщо errexitвона також не була встановлена. З іншого боку, інтерактивна оболонка тире не вийде, навіть якщо set -eвона раніше була запущена.


Якщо тире не виходить із встановленням -e; встановити -у; unset aa; echo $ aa, то тире неправильно.
schily

@schily Коли я вперше помітив це, я зрозумів, що автори тире знають краще, ніж я, і, можливо, в специфікаціях POSIX була якась неоднозначність, але перевіривши pubs.opengroup.org/onlinepubs/9699919799/utilities/… , я погодьтеся, схоже на помилку, добре.
Ентоні Геоґеган

Існує просте правило: коли і Korn Shell, і Bourne Shell погоджуються, і інша реалізація оболонки має відхилення, то інша оболонка поводиться неправильно.
schily
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.