Це старе запитання, але жоден з відповідей тут не обговорює використання set -e
ака set -o errexit
в сценаріях обробки пакунків Debian. Використання цієї опції є обов'язковим у цих сценаріях відповідно до політики Debian; Намір, мабуть, уникнути будь-якої можливості нездійсненної умови помилки.
Що це означає на практиці, це те, що ви повинні розуміти, за яких умов команди, які ви виконуєте, можуть повернути помилку, і обробляти кожну з цих помилок явно.
Поширеними є "наприклад" diff
(повертає помилку, коли є різниця) та grep
(повертає помилку, коли немає відповідності). Ви можете уникнути помилок при явній обробці:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Зверніть увагу також і на те, як ми беремося, щоб в повідомлення включати ім'я поточного сценарію та писати діагностичні повідомлення до стандартної помилки замість стандартного виводу.)
Якщо явне поводження дійсно не потрібне чи корисне, явно нічого не робіть:
diff this that || true
grep cat food || :
(Використання оболонок :
дещо незрозуміле, але досить часто зустрічається.)
Просто ще раз,
something || other
це скорочення для
if something; then
: nothing
else
other
fi
тобто ми прямо кажемо, що його other
слід запускати, якщо і лише у разі something
невдачі. Довга рука if
(та інші заяви управління потоком оболонки, такі як while
, until
) також є коректним способом вирішення помилки (дійсно, якщо вона не була, сценарії оболонки зset -e
ніколи не могли б містити заяви контролю потоку!)
А також, якщо бути явним, за відсутності обробника, як це, set -e
це призвело б до того, що весь скрипт негайно вийшов з ладу з помилкою, якщо diff
знайшов різницю, або якщо grep
не знайшов відповідності.
З іншого боку, деякі команди не створюють стану виходу з помилки, коли ви хочете, щоб вони цього хотіли. Зазвичай проблематичними є команди find
(стан виходу не відображає, чи були фактично знайдені файли) та sed
(статус виходу не виявить, чи отримав сценарій який-небудь ввід чи реально виконав якісь команди успішно). У деяких сценаріях простою охороною є передача команди, яка кричить, якщо немає виводу:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Слід зазначити, що статус виходу трубопроводу - це стан виходу останньої команди в цьому трубопроводі. Отже, наведені вище команди фактично повністю маскують статус find
та sed
, і лише повідомляють, чи grep
вдалося остаточно досягти.
(Bash, звичайно, є set -o pipefail
, але сценарії пакетів Debian не можуть використовувати функції Bash. Політика твердо диктує використання POSIXsh
для цих сценаріїв, хоча це не завжди було так.)
У багатьох ситуаціях на це потрібно окремо стежити, коли кодує оборонно. Іноді доводиться, наприклад, пройти тимчасовий файл, щоб ви могли побачити, чи успішно закінчилася команда, яка створила цей результат, навіть коли ідіома та зручність інакше спрямовували б вас використовувати конвеєр оболонки.