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

Когда использовать set -e

Я встретил set -e некоторое время назад, и я признаю, что мне это нравится. Теперь, через некоторое время, я вернусь, чтобы написать скрипт bash.

Мой вопрос в том, есть ли какие-либо рекомендации по использованию set -e и когда не использовать его (.eg в сценариях с малым/большим шрифтом и т.д.), или я должен использовать шаблон, например cmd || exit 1, для отслеживания ошибок?

4b9b3361

Ответ 1

Да, вы всегда должны его использовать. Люди высмеивают Visual Basic все время, говоря, что это не настоящий язык программирования, отчасти из-за его утверждения "On Error Resume Next". Но это по умолчанию в оболочке! set -e должен был быть значением по умолчанию. Потенциал катастрофы слишком высок.


В тех местах, где это нормально для команды, вы можете использовать || true или сокращенную форму ||:, например.

grep Warning build.log ||:

На самом деле вам нужно сделать еще один шаг и

set -eu
set -o pipefail

вверху каждого bash script.

-u позволяет ошибочно ссылаться на несуществующую переменную среды, такую ​​как ${HSOTNAME}, за счет потребности в некоторой гимнастике с проверкой ${#}, прежде чем вы обратитесь к ${1}, ${2} и т.д..

pipefail делает такие вещи, как misspeled-command | sed -e 's/^WARNING: //', вызывает ошибки.

Ответ 2

Если ваш код script корректно и правильно проверяет ошибки и обрабатывает их соответствующим образом, то вам, вероятно, никогда не понадобится или не захочется использовать set -e.

С другой стороны, если ваш script представляет собой простой последовательный список команд, которые будут запускаться один за другим, и если вы хотите, чтобы script завершался, если какой-либо из них вышел из строя, затем придерживая set -e на top будет именно тем, что вы хотели бы сделать, чтобы ваш script простой и незагроможденный. Прекрасным примером этого может быть, если вы создаете script для компиляции набора источников и хотите, чтобы компиляция остановилась после первого файла с ошибками.

Более сложные скрипты могут комбинировать эти методы, поскольку вы можете использовать set +e, чтобы снова отключить его эффект и вернуться к явной проверке ошибок.

Обратите внимание, что хотя set -e предполагается, что оболочка выйдет из IFF, любая непроверенная команда завершится неудачей, разумно снова отключить ее, когда ваш код выполняет собственную обработку ошибок, так как могут быть странные случаи, когда команда вернет ненужный статус выхода, которого вы не ожидаете, и, возможно, даже такие случаи, которые вы не можете заразиться при тестировании, и когда внезапное фатальное завершение вашего script оставит что-то в плохом состоянии. Поэтому не используйте set -e или не включайте его после краткого использования, если вы действительно не знаете, что хотите.

Обратите внимание, что вы все равно можете определить обработчик ошибок с trap ERR, чтобы что-то сделать в случае ошибки, когда действует set -e, поскольку это все равно будет выполняться до выхода оболочки.

Ответ 3

Вы любите это!?

Для себя, я предпочитаю в широком, имея в моей .bashrc строку, подобную этой:

trap '/usr/games/fortune /usr/share/games/fortunes/bofh-excuses' ERR

(на debian: apt-get install fortunes-bofh-excuses: -)

Но это только мое предпочтение; -)

Более серьезно

lastErr() {
    local RC=$?
    history 1 |
         sed '
  s/^ *[0-9]\+ *\(\(["'\'']\)\([^\2]*\)\2\|\([^"'\'' ]*\)\) */cmd: \"\3\4\", args: \"/;
  s/$/", rc: '"$RC/"
}
trap "lastErr" ERR

Gna
bash: Gna : command not found
cmd: "Gna", args: "", rc: 127

Gna gna
cmd: "Gna", args: "gna", rc: 127

"Gna gna" foo
cmd: "Gna gna", args: "foo", rc: 127

Хорошо, оттуда вы могли бы:

trap "lastErr >>/tmp/myerrors" ERR
"Gna gna" foo

cat /tmp/myerrors 
cmd: "Gna gna", args: "foo", rc: 1

Или лучше:

lastErr() {
local RC=$?
history 1 |
     sed '
  s/^ *[0-9]\+ *\(\(["'\'']\)\([^\2]*\)\2\|\([^"'\'' ]*\)\) */cmd: \"\3\4\", args: \"/;
  s/$/", rc: '"$RC/
  s/^/$(date +"%a %d %b %T ")/"
}
"Gna gna" foo

cat /tmp/myerrors 
cmd: "Gna gna", args: "foo", rc: 1
Tue 20 Nov 18:29:18 cmd: "Gna gna", args: "foo", rc: 127

... Вы даже можете добавить другую информацию, например $$, $PPID, $PWD или, возможно, свою..

Ответ 4

Если этот параметр включен, если простая команда не выполняется по любой из причин, перечисленных в Последствиях ошибок оболочки, или возвращает значение состояния выходa > 0 и не является частью составного списка через некоторое время, пока, или если ключевое слово и не является частью списка AND или OR и не является конвейером, которому предшествует! зарезервированное слово, то оболочка должна немедленно выход.