Travis CI와 유사한 매우 컴팩트한 버전의 함수를 생성하려고 합니다.travis_retry
. 함수는 기본적으로 제공된 인수를 명령으로 세 번 시도하고 반복적으로 실패하면 실패(1을 반환)하는 고차 함수여야 합니다.
다음은 내가 시도한 몇 가지 시도이지만 그 중 어느 것도 내 기대에 미치지 못했습니다.
retry() {
"${@}" || "${@}" || "${@}"
}
이는 간단한 명령(예 echo ciao
: )에서는 작동하는 것처럼 보이지만 중요한 표현식에서는 실패합니다.
$ retry if true; then echo hello; fi; false
bash: syntax error near unexpected token `then'
나는 함수가 hello
세 번 인쇄하고 반환할 것으로 예상했습니다 1
( false
마지막으로 평가되었으므로).
두 번째 시도는 다음과 같습니다.
retry() {
$* || $* || $*
}
이것은 이전 것과 같습니다. 세 번째 버전도 시도했지만 eval
당연히 작동하지 않습니다. 이 시점에서 여기에 몇 가지 기본 사항이 누락된 것이 분명하므로 계속 시도하기보다는 이해하고 싶습니다.
답변1
함수를 사용하는 경우 여러 문자열 인수만 전달할 수 있으므로 간단한 명령에 대한 인수로만 해석될 수 있습니다. 임의의 셸 코드를 문자열로 전달할 수 있지만 함수에 리터럴 문자열로 전달할 수 있도록 코드를 평가하고 인용해야 합니다.
retry() { eval " $1" || eval " $1" || eval " $1"; }
retry 'if true; then echo hello; fi; false'
아니면 당신의 것:
retry() { "$@" || "$@" || "$@"; }
라고 불리는:
retry eval 'if true; then echo hello; fi; false'
그러나 별칭을 사용하면 다음을 수행할 수 있습니다.
alias 'retry{{={
attempts=0
until {' '}}=
}; do
if (( ++attempts >= 3 )); then
echo >&2 "Giving up after $attempts attempts"
! break
fi
done
}'
그런 다음:
bash-5.0$ retry{{ echo test; false; }}
test
test
test
Giving up after 3 attempts
이는 C의 전처리기 매크로처럼 코드가 완전히 구문 분석되기 전에 코드를 읽을 때 별칭이 확장되기 때문에 작동합니다.
답변2
또 다른 옵션은 bash의 첫 번째 원칙 대신 재시도 명령을 사용하는 것입니다.
여기서는 매번 실패하고 세 번 시도한 후에 포기하는 중요하지 않은 표현식을 다시 시도합니다.
~$ ./retry --times 3 -- sh -c "echo hello; echo there; false"
hello
there
retry: sh returned 1, backing off for 10 seconds and trying again...
hello
there
retry: sh returned 1, backing off for 10 seconds and trying again...
hello
there
retry: sh returned 1, backing off for 10 seconds and trying again...
https://github.com/minfrin/retry
최신 Debian, Ubuntu 및 Nix와 함께 즉시 사용할 수 있습니다.