그래서 실패했거나 명령줄 오류가 발생하여 다시 시도하려고 합니다.하지만재시도할 때마다 다른 플래그가 표시됩니다.
나는 실패 시 명령을 재시도하는 방법을 이미 알고 있습니다.
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
두 매개변수의 합과 같기 때문에 도움이 되지 않습니다.foo
bar
또한 "${@/pattern/pattern --otherflag}"
각 위치 인수에 대해 개별적으로 대체가 이루어지므로 및 인수를 사용하면 ls
두 foo 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}"
나머지 매개변수도 마찬가지입니다.
다소 관련됨:변수에 저장된 명령을 어떻게 실행할 수 있나요?