||를 사용하여 bash 함수 연산자를 압축하여 명령을 다시 시도하세요.

||를 사용하여 bash 함수 연산자를 압축하여 명령을 다시 시도하세요.

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와 함께 즉시 사용할 수 있습니다.

관련 정보