У меня есть bash shell script с заголовком #!/bin/bash -e
.
Когда я запустил script, он будет прерван после запуска команды grep
, но когда я удалю параметр -e
, тогда script можно запустить нормально. В чем смысл параметра -e
?
У меня есть bash shell script с заголовком #!/bin/bash -e
.
Когда я запустил script, он будет прерван после запуска команды grep
, но когда я удалю параметр -e
, тогда script можно запустить нормально. В чем смысл параметра -e
?
Опция -e
означает "если какой-либо конвейер когда-либо заканчивается статусом выхода с ненулевым (" ошибка "), немедленно завершите script". Поскольку grep
возвращает статус выхода 1
, когда он не находит никакого совпадения, это может привести к тому, что -e
завершит script, даже если не было реальной "ошибки".
Если вы хотите сохранить параметр -e
, но также имеете команду grep
, которая может не найти совпадений, вы можете добавить || :
в команду grep
. Это означает "или, если команда grep
возвращает ненулевой статус выхода, запустите :
(который ничего не делает)"; поэтому чистый эффект заключается в отключении -e
для команды grep
. Итак:
grep PATTERN FILE... || :
Отредактировано для добавления: Вышеупомянутый подход отбрасывает каждую ошибку: если grep
возвращает 1
, потому что не найдено совпадений, которые игнорируются, но также, если grep
возвращает 2
, потому что там была ошибкой, которая игнорировалась, и если grep
не находится в пути (поэтому Bash возвращает 127
), это игнорируется — и так далее. Таким образом, вместо :
, вероятно, лучше использовать команду, которая проверяет код результата и повторно выдает ошибку, если это что-то другое, кроме 1
. Например:
grep PATTERN FILE || (( $? == 1 ))
Но это разрушает статус выхода; обычно, когда неудавшаяся команда завершает Bash script с -e
, script вернет статус завершения команды, но в приведенном выше примере script просто вернет 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 "[email protected]" || 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
в этом script, мы можем просто назвать функцию grep
:
function grep () {
local exit_code
command grep "[email protected]" || exit_code=$?
return $(( exit_code == 1 ? 0 : exit_code ))
}
grep PATTERN FILE # won't kill script if no matches are found
(обратите внимание на использование command
для обхода функции оболочки внутри своего собственного тела: мы хотим, чтобы функция вызывала обычную программу grep
, а не бесконечно возвращалась).
В дополнение к односимвольным параметрам командной строки оболочки (см. раздел "Установка встроенных" ) существует несколько многосимвольных опций, которые вы можете использовать.
И если мы посмотрим, что set
должно сказать:
-e
Выйдите немедленно, если конвейер (см. "Трубопроводы" ), который может состоять из одной простой команды (см. "Простые команды" ), команды подголовника, заключенной в круглые скобки (см. "Групповая группировка" ), или одной из команд, выполняемых как часть списка команд, фигурные скобки (см. Командная группа) возвращает ненулевой статус.
Итак, когда вы говорите bash -e
, если какая-либо команда в script терпит неудачу (т.е. возвращает статус отсутствия нулевого статуса), тогда весь script немедленно завершится с ошибкой. Таким образом, ваш grep
возвращает ненулевое значение, потому что оно не соответствует и завершает работу всего script, если вы укажете -e
при запуске bash.