Подтвердить что ты не робот

Каково значение параметра -e для командной строки оболочки bash?

У меня есть bash shell script с заголовком #!/bin/bash -e.

Когда я запустил script, он будет прерван после запуска команды grep, но когда я удалю параметр -e, тогда script можно запустить нормально. В чем смысл параметра -e?

4b9b3361

Ответ 1

Опция -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, а не бесконечно возвращалась).

Ответ 2

Из прекрасного руководства:

В дополнение к односимвольным параметрам командной строки оболочки (см. раздел "Установка встроенных" ) существует несколько многосимвольных опций, которые вы можете использовать.

И если мы посмотрим, что set должно сказать:

-e
Выйдите немедленно, если конвейер (см. "Трубопроводы" ), который может состоять из одной простой команды (см. "Простые команды" ), команды подголовника, заключенной в круглые скобки (см. "Групповая группировка" ), или одной из команд, выполняемых как часть списка команд, фигурные скобки (см. Командная группа) возвращает ненулевой статус.

Итак, когда вы говорите bash -e, если какая-либо команда в script терпит неудачу (т.е. возвращает статус отсутствия нулевого статуса), тогда весь script немедленно завершится с ошибкой. Таким образом, ваш grep возвращает ненулевое значение, потому что оно не соответствует и завершает работу всего script, если вы укажете -e при запуске bash.