나는 주로 시작/중지/상태 방식으로 작동하는 단계적 작업으로 구성된 스크립트를 가지고 있습니다.
제가 겪고 있는 문제는 시작 시 모든 작업이 실패할 수 있으며 안전한 롤백을 위해 중지 작업을 사용해야 한다는 것입니다.
Bash에서 어떻게 할 수 있나요?
나는 다음과 같은 것을 생각하고 있습니다 (작동하지 않습니다).
operation1_start() {}
operation2_start() {}
operation1_stop() {}
operation2_stop() {}
operation1_start && rollback=operation1_stop;$rollback
test_validity || $($rollback)
operation2_start && rollback=operation2_stop;$rollback
test_validity || $($rollback)
답변1
다음 두 가지 쉘 프로그래밍 기술이 유용할 수 있습니다.
- 당신이 달리면
set -e
, 명령이 0이 아닌 상태를 반환하면(if
또는while
조건과 같은 명백한 것이 없는 한) 쉘은 즉시 종료됩니다. - 당신이 달리면
trap 'somecode' EXIT
, 스크립트가 종료되면(명시적으로 또는 암시적 종료로 인해set -e
)somecode
먼저 실행됩니다. 항목에는somecode
마지막$?
명령의 상태가 포함됩니다.
그러므로 다음과 같이 작성할 수 있습니다.
(set -e; trap 'abort operation a' EXIT; perform operation a; )
ERR
Bash에서는 대신 에 트랩을 설정할 수 있습니다 EXIT
. set -e
이러한 트랩은 로 인해 쉘이 종료될 때만 실행됩니다. 게다가 ERR
트랩은 함수에 대해 로컬입니다.
set -e
operation_a () {
trap 'abort code' ERR
perform operation a
}
가능하다면 초안을 먼저 작성하고 실행하는 것이 더 쉬울 것입니다.원자거래를 제출하기 위한 조치입니다. 예를 들어 파일에 쓰는 경우 대상 디렉터리의 임시 파일에 쓴 다음 mv
새 파일을 제자리로 이동을 호출합니다. 이는 kill -9
정전으로 인해 스크립트가 종료되면 롤백이 수행되지 않기 때문에 롤백 코드 형태로 정리가 필요한 모든 것보다 훨씬 강력합니다 .
답변2
실제로 배열을 사용하여 이를 달성했습니다. 잘 작동하는 것 같습니다(심지어 롤백임을 함수에 알리기 위해 추가 매개변수도 추가했습니다).
abc()
{
echo "abc----$1";
}
cda()
{
echo "cda----$1";
}
safe_rollback=( )
add_rollback()
{
safe_rollback[${#safe_rollback[*]}]=$1;
}
run_rollback()
{
while [ ${#safe_rollback[@]} -ge 1 ]; do
${safe_rollback[${#safe_rollback[@]}-1]} rollback;
unset safe_rollback[${#safe_rollback[@]}-1];
done
}
add_rollback cda
add_rollback abc
run_rollback
답변3
실제로 수행하는 작업은 다양한 시나리오에 따라 시작/상태/계속/롤백/중지 유형 작업을 수행할 수 있는 빌드 프로세스의 복제처럼 들립니다. 쉘 스크립트와 함께 Makefile을 사용하면 상태를 결정하는 상호 종속성을 더 우아하게 정의할 수 있기 때문에 이 효과를 더 우아하게 얻을 수 있습니다.