У меня есть сценарий Bash, который использует set -o errexit
так, чтобы в случае ошибки весь сценарий выходил в точке сбоя.
Сценарий запускает curl
команду, которая иногда не может получить нужный файл - однако, когда это происходит, сценарий не завершается с ошибкой.
Я добавил for
цикл в
- сделать паузу на несколько секунд, затем повторить
curl
команду - используйте
false
в нижней части цикла for для определения ненулевого состояния выхода по умолчанию - если команда curl выполнена успешно - цикл прерывается, и состояние выхода последней команды должно быть равно нулю.
#! /bin/bash
set -o errexit
# ...
for (( i=1; i<5; i++ ))
do
echo "attempt number: "$i
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
if [ -f ~/.vim/autoload/pathogen.vim ]
then
echo "file has been retrieved by curl, so breaking now..."
break;
fi
echo "curl'ed file doesn't yet exist, so now will wait 5 seconds and retry"
sleep 5
# exit with non-zero status so main script will errexit
false
done
# rest of script .....
Проблема в том, что при curl
сбое команды цикл повторяет команду пять раз - если все попытки не удаются, цикл for завершается и основной сценарий возобновляется - вместо запуска errexit
.
Как я могу получить весь скрипт для выхода, если этот curl
оператор не выполняется?
источник
true
перед оператором break явное и обеспечить выходное значение цикла?exit 1
когда простоexit
бы сработало. Это вопрос стиля, и у других может быть свое мнение.exit
как простой выход - который завершает скрипт самостоятельно.exit 1
будет читать мне как «сигнал» для какого-то другого процесса (то естьerrexit
) - что он должен завершить сценарий на основе «результата»exit 1
. - так что я пошел с,exit
но спасибо за объяснениеexit 1
. Это никак не влияетerrexit
. Это просто говорит вызывающей программе, что что-то пошло не так.false
Команда содержит одно утверждение:exit(1)
. 99,9% команд Unix возвращают 0 в случае успеха и ненулевое значение в случае ошибки. Твои тоже должны.Если вы
errexit
установили, тоfalse
оператор должен немедленно завершить работу скрипта. То же самое, еслиcurl
команда не удалась.Ваш пример сценария, как написано, должен завершиться после первого
curl
сбоя команды при первомfalse
вызове, если установлен errexit.Чтобы увидеть, как это работает (я использую сокращение
-e
для установкиerrexit
:Таким образом, если
curl
команда выполняется более одного раза, этот сценарий неerrexit
установлен.источник
set -e
более тонкий, чем это. Он не завершится после первой неудачной команды в цикле. Вы можете доказать это себе, запустив(set -e; for (( i=1; i<5; i++ )); do echo $i; false; done || echo "FAIL"; )
и заметив, что код выполняетсяfalse
четыре раза. Для получения дополнительной информацииset -e
см . FAQ Грега # 105 .errexit
не установлены. Пожалуйста, примените логику к сценарию в вопросе. Запустите это:(set -e; for (( i=1; i<5; i++ )); do echo $i; false; done ; echo still here )
Да, тестирование возвращаемых значений с помощьюif
while
||
&&
etc не вызывает ошибку errexit. Оригинальный скрипт не сделал||
цикл for.set -o errexit
команду в своем примере кода, добавил ее сейчас - и для меня это не было ошибкой выхода, как ожидалось. Мне нужно было сохранитьfalse
как последнюю команду в цикле for, затем закрыть цикл с помощьюdone || exit [1]
- тогда это сработало хорошо!set -o errexit
может быть сложно в циклах и подоболочках, потому что вы должны пройти путь обратно из процесса.Прерывание цикла (даже при нормальной работе) считается плохой практикой. Вы можете называть меня старой школой, чтобы я предпочел цикл while, а не цикл for для двух условий, но я считаю, что лучше читать:
источник
Если
errexit
установлено иcurl
команда не выполняется, скрипт завершается сразу после неудачной команды curl. В руководстве по bash нет подсказки, в которойset -e
игнорируется какой-либо сбойный статус возврата одного в составной команде. Это было бы только в том случае, если составная команда выполняется в контексте, гдеset -e
игнорируется.https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin
Попробуйте слегка адаптированный пример, опубликованный RobertL. Это останавливается на первой итерации for сразу после ложной команды:
источник
Вы можете просто добавить параметр --fail к команде curl, это решит вашу проблему, скрипт завершится ошибкой и завершится с ошибкой, если команда curl не удастся, если это также очень полезно при использовании curl в конвейере jenkins:
источник