У мене є скрипт оболонки bash із заголовком #!/bin/bash -e.
Коли я запускаю сценарій, він буде перерваний після grepзапуску команди, але коли я видалю параметр -e, то скрипт може запускатися нормально. Що означає параметр -e?
У мене є скрипт оболонки bash із заголовком #!/bin/bash -e.
Коли я запускаю сценарій, він буде перерваний після grepзапуску команди, але коли я видалю параметр -e, то скрипт може запускатися нормально. Що означає параметр -e?
-e варіант для Баша: serverfault.com/questions/391255 / ... .
Відповіді:
В -eопції означає : «Якщо трубопровід коли - або закінчується зі статусом ненульовим (" помилка "), завершити скрипт негайно». Оскільки grepповертає статус виходу, 1коли він не знаходить жодного збігу, це може призвести -eдо завершення роботи сценарію, навіть якщо не було справжньої "помилки".
Якщо ви хочете зберегти -eваріант, але є grepкоманда , яка не може законним чином знайти не матчі, ви можете додати || :до grepкоманді. Це означає "або, якщо grepкоманда повертає ненульовий статус виходу, запустити :(що нічого не робить)"; тому чистий ефект полягає у відключенні -eдля grepкоманди. Так:
grep PATTERN FILE... || :
Відредаговано для додавання: Вищевказаний підхід відкидає кожну помилку: якщо grepповертається, 1оскільки не знайдено збігів, це ігнорується, а також якщо grepповертається, 2оскільки сталася помилка, яка ігнорується, а якщо grepнемає в шляху (тому Bash повертається 127), це ігнорується - і так далі. Тож замість того :, можливо, краще використовувати команду, яка перевіряє код результату та повторно видає помилку, якщо це щось інше, ніж 1. Наприклад:
grep PATTERN FILE || (( $? == 1 ))
Але це руйнує статус виходу; зазвичай, коли невдала команда закінчує сценарій Bash -e, скрипт повертає статус виходу команди, але у наведеному вище прикладі сценарій просто повертається 1. Якщо (і лише якщо) нас це турбує, ми можемо це виправити, написавши щось подібне:
grep PATTERN FILE || exit_code=$?
if (( exit_code > 1 )) ; then
exit $exit_code
fi
(перший рядок c / o коментар dsummersl ).
На даний момент, мабуть, найкраще створити функцію оболонки, яка б обробляла це для нас:
function grep_no_match_ok () {
local exit_code
grep "$@" || exit_code=$?
return $(( exit_code == 1 ? 0 : exit_code ))
}
(зверніть увагу на використання returnзамість exit; ми дозволимо -eобробляти вихід, коли це доречно); таким чином, ми можемо просто написати:
grep_no_match_ok PATTERN FILE # won't kill script if no matches are found
Насправді, оскільки ми, швидше за все, хочемо використовувати цю функцію для всіх випадків grepв цьому сценарії, ми можемо насправді просто назвати функцію grep:
function grep () {
local exit_code
command grep "$@" || exit_code=$?
return $(( exit_code == 1 ? 0 : exit_code ))
}
grep PATTERN FILE # won't kill script if no matches are found
(зверніть увагу на використання функції commandобходу оболонки у своєму власному тілі: ми хочемо, щоб функція викликала звичайну програму grep, а не повторювала нескінченно).
grep XXX FILE || exitcode=$?. Супер зручно!
На додаток до параметрів командного рядка оболонки з одним символом (див. Набір вбудованих), є кілька багатосимвольних параметрів, якими ви можете скористатися.
І тоді, якщо ми подивимося, що setсказати:
-e
Негайно закрийте конвеєр (див. Конвеєри), який може складатися з однієї простої команди (див. Прості команди), команди під оболонки, укладеної в дужки (див. Групування команд), або однієї з команд, що виконуються як частина списку команд, дужки (див. Групування команд) повертає ненульовий статус.
Отже, коли ви говорите bash -e, якщо будь-яка команда у сценарії зазнає невдачі (тобто повертає ненульовий статус існування), то весь сценарій негайно виходить з ладу. Отже, ви grepповертаєте ненульове значення, оскільки воно не збігається, і це вимикає весь сценарій, якщо ви вказали -eпід час запуску bash.
setале хотів побачити це в посібнику. Мені було цікаво, чому я цього не побачив man bash, це тому, що я перейшов прямо до перерахованих параметрів і пропустив абзац, який сказав: "Усі параметри оболонки з одним символом, задокументовані в описі набору вбудованих команд, включаючи -o може використовуватися як опція при виклику оболонки ". Все там!
-eможливості bash, так що ж насправді відбувається в цьому випадку? :(