Є ще кілька способів, за допомогою яких можна підійти до цієї проблеми. Припустимо, що однією з ваших вимог є запустити скрипт / функцію оболонки, що містить кілька команд оболонки, і перевірити, чи сценарій успішно запустився та викинути помилки у разі відмов.
Команди оболонки, як правило, покладаються на повернуті коди виходу, щоб повідомити оболонці, чи вона була успішною чи не вдалася через якісь несподівані події.
Тож те, що ви хочете зробити, попадає на ці дві категорії
- помилка виходу
- вихід і очищення за помилкою
Залежно від того, який ви хочете зробити, доступні варіанти використання оболонок. У першому випадку, оболонка надає можливість з set -e
і для другого ви могли б зробити trap
наEXIT
Чи варто використовувати exit
в моєму сценарії / функції?
Використання, exit
як правило, підвищує читабельність У певних процедурах, коли ви дізнаєтесь відповідь, ви хочете негайно вийти з програми виклику. Якщо рутина визначена таким чином, що вона не потребує подальшої очищення, як тільки виявить помилку, не виходить з ладу негайно означає, що вам доведеться написати більше коду.
Тож у випадках, якщо вам потрібно виконати очищення сценарію для очищення припинення сценарію, його краще використовувати не використовувати exit
.
Чи слід використовувати set -e
для помилки при виході?
Немає!
set -e
була спроба додати "автоматичне виявлення помилок" до оболонки. Її метою було змусити оболонку перервати будь-який час, коли сталася помилка, але вона має багато потенційних підводних каменів, наприклад,
Команди, які є частиною тесту if, не захищені. У прикладі, якщо ви очікуєте, що він порушиться при test
перевірці на неіснуючий каталог, він би не став, він перейде до іншого умови
set -e
f() { test -d nosuchdir && echo no dir; }
f
echo survived
Команди в трубопроводі, відмінному від останнього, не застраховані. У наведеному нижче прикладі, оскільки код виходу останньої (найправішої) команди вважається ( cat
), і він був успішним. Цього можна уникнути, встановивши set -o pipefail
варіант, але це все-таки застереження.
set -e
somecommand that fails | cat -
echo survived
Рекомендовано для використання - trap
при виході
Вирок , якщо ви хочете , щоб мати можливість обробляти помилку замість того , щоб сліпо виходу, замість того , щоб використовувати set -e
, використовувати trap
на ERR
сигнал псевдо.
ERR
Пастка не для запуску коду , коли сама оболонка виходить з ненульовим кодом помилки, але коли будь-яка команда запуску цієї оболонки , яка не є частиною стану (наприклад , в разі cmd
, чи cmd ||
) завершується зі статусом ненульовим .
Загальна практика полягає в тому, що ми визначаємо оброблювач пастки для надання додаткової інформації про налагодження, на якій лінії та що викликає вихід. Запам’ятайте код виходу останньої команди, яка викликала ERR
сигнал, як і раніше буде доступна в цьому пункті.
cleanup() {
exitcode=$?
printf 'error condition hit\n' 1>&2
printf 'exit code returned: %s\n' "$exitcode"
printf 'the command executing at the time of the error was: %s\n' "$BASH_COMMAND"
printf 'command present on line: %d' "${BASH_LINENO[0]}"
# Some more clean up code can be added here before exiting
exit $exitcode
}
і ми просто використовуємо цей обробник, як показано нижче вгорі сценарію, який не працює
trap cleanup ERR
Збираючи це разом на простий скрипт, який міститься false
у рядку 15, інформація, яку ви отримаєте
error condition hit
exit code returned: 1
the command executing at the time of the error was: false
command present on line: 15
trap
Також варіанти незалежно від помилки просто запустити очищення по завершенню оболонки (наприклад , ваші виїзди з скрипт оболонки), по сигналу EXIT
. Ви також можете потрапити в декілька сигналів одночасно. Список підтримуваних сигналів, на які слід відключити, можна знайти на сторінці trap.1p - керівництво Linux
Ще одне, що слід зауважити, - це зрозуміти, що жоден із запропонованих методів не працює, якщо ви маєте справу з суб-оболонками.
На під-оболонці з set -e
не буде працювати. Ліцензія false
обмежена під-оболонкою і ніколи не поширюється на батьківську оболонку. Щоб зробити тут помилку, додайте власну логіку(false) || false
set -e
(false)
echo survived
Те ж саме відбувається і з trap
. Логіка нижче не працює з причин, зазначених вище.
trap 'echo error' ERR
(false)