성공할 때까지 실패 시 명령을 재시도하되, 다른 플래그를 사용하십시오.

성공할 때까지 실패 시 명령을 재시도하되, 다른 플래그를 사용하십시오.

그래서 실패했거나 명령줄 오류가 발생하여 다시 시도하려고 합니다.하지만재시도할 때마다 다른 플래그가 표시됩니다.

나는 실패 시 명령을 재시도하는 방법을 이미 알고 있습니다.

while ! "$@"
do
  :
  sleep 1
done

예를 들어, 실패한 명령에 대해 의도적으로 위 함수를 사용하여 설명하겠습니다.

retry ls test # here this will usually fail and thus retry infinitely

나는이 사실을 알고:

  • 무한 재시도(재시도된 명령이 성공하거나 셸에서 성공으로 해석된 종료 코드를 반환할 때까지)
  • 실패 이외의 어떤 종류의 오류/종료 코드도 고려하지 않습니다.

위의 내용은 모두 원하는/예상되는 효과입니다.

내가 추가하고 싶은 유일한 것은 N 명령을 "재시도"할 때 추가 플래그에 대한 지원입니다(이를 함수에 대한 인수로 제공하거나 적절하게 함수에 하드코딩해야 합니다...)

내가 시도한 것은 다음과 같습니다.

bash
while ! "$(echo "$@" | sed "s/^pattern/pattern --otherflag/g")"
do
  :
  sleep 1
done

용법:

retry ls pattern

새 명령은 어디에 있게 될까요? ls pattern --otherflag(분명히 실패하겠지만 그게 요점이 아닙니다.)

두 번째 방법:

while ! "${@/pattern/pattern --otherflag}"
do
  :
  sleep 1
done

사용법은 위와 동일합니다..

여기서는 위와 동일한 결과를 제공합니다.

이제 언뜻 작동하는 것처럼 보이지만 제공/실패한 명령에 어떤 종류의 따옴표(일반적으로 따옴표 없음)가 포함되어 있으면 출력/재시도 명령에서 따옴표가 제거/무시됩니다...

따라서 위의 두 가지 방법/예를 따르면 이와 같은 명령은 ls pattern "file"따옴표 없이 실행됩니다 ls pattern --otherflag file(작은 따옴표를 사용해도 동일한 일이 발생함).file

이 문제를 해결하기 위해 나는 이것을 시도했습니다답변기능을 수행 quote했지만 만족스러운 결과를 얻지 못했습니다. 또한 실패 시 추가된 플래그를 기다리거나 사용하는 것이 아니라(예: 재시도 기능이 시작될 때) 대신 실패하기 전에 추가 플래그를 사용하여 실행하는 것으로 보입니다.

가능하다면 블록/조건을 사용하고 싶지 않으며 if가능한 한 위의 스니펫에 가깝게 유지하는 것을 선호합니다. 선호 bash및/또는 sh대안. 모든 피드백/답변을 환영합니다.

답변1

스크립트가 호출 retry.sh되고 쉘에서 명령줄을 통해 retry.sh ls "foo bar"스크립트의 위치 인수(매개변수, 즉 $1... $2) 는 ls및 가 됩니다 foo bar. 따옴표는 쉘 명령줄에서 공백과 기타 특수 문자를 보호하는 방법이지만 시작된 스크립트에는 더 이상 따옴표가 존재하지 않습니다. 대신 기본적으로 문자열 배열이 있습니다.

이제 "$@"다양한 인수가 올바르게 처리됩니다. 각 인수를 다른 단어로 확장합니다. 그러나 이렇게 하면 단어 분할을 사용하여 공백으로 분할하는 대신 인수를 문자열에 "$(echo "$@" | sed "s/^pattern/pattern --otherflag/g")"연결 echo하고 전체 명령 주위의 따옴표를 대체하여 문자열로 유지합니다. 분할은 원래 매개변수 사이의 분리가 손실되고 하나의 매개변수가 foo bar두 매개변수의 합과 같기 때문에 도움이 되지 않습니다.foobar

또한 "${@/pattern/pattern --otherflag}"각 위치 인수에 대해 개별적으로 대체가 이루어지므로 및 인수를 사용하면 lsfoo bar단어 "${@/ls/ls --otherflag}"가 생성됩니다 ls --otherflag. 이는 마치 쉘 명령줄에서 실행되는 ls --otherflag것처럼 문자 그대로 라는 명령을 찾습니다 ."ls --otherflag"


원하는 것은 ls, --otherflag, foo bar즉 플래그를 추가 매개변수로 추가하는 것입니다.

때를할 수 있다여기에서 모든 인수를 가져와서 $@셸 처리를 위해 이스케이프하고 함께 연결하여 유효한 명령줄을 생성한 다음 해당 명령줄을 편집하고 를 사용하여 셸에 다시 공급합니다. eval목록을 목록으로 처리하는 것이 더 안전합니다.

마지막에 매개변수를 추가하는 것은 상대적으로 쉽습니다.

#!/bin/sh
if ! "$@"; then
    echo "failed, retrying..."
    if ! "$@" --otherflag; then
        echo "nope, still failed"
    fi
fi

중간에 하나를 추가하려면 배열이나 슬라이스가 필요합니다 $@. 예를 들어 두 번째 위치에 플래그를 추가합니다.

#!/bin/bash
if ! "$@"; then
    echo "failed, retrying..."
    if ! "$1" --otherflag "${@:2}"; then
        echo "nope, still failed"
    fi
fi

"${@:n:m}"처음으로 확장인덱스에서 시작하는 위치 매개변수N, 또는 목록 끝까지주어지지 않았습니다. "$1"첫 번째 매개변수( 와 동일 "${@:1:1}")와 "${@:2}"나머지 매개변수도 마찬가지입니다.

다소 관련됨:변수에 저장된 명령을 어떻게 실행할 수 있나요?

관련 정보