일부 서버를 시작하려면 다음 bash 스크립트가 있습니다.
services=(
account-service
reminder-service
activity-service
socket-service
chat-service
web-app
)
for s in "${services[@]}"; do
(
set -e;
cd "$s"
git pull
npm start || exit 1 # always fails
) &
sleep 1;
done
wait;
때때로 git pull
명령이 실패합니다. 그러나 결함은 로그 깊은 곳에 있으며 항상 명확하지는 않습니다. 서브셸의 명령 중 하나가 1로 종료되면 전체 스크립트를 어떻게 중단합니까?
답변1
글쎄요, 아마도 wait
다음과 같이 진술을 변경해 보세요:
while true; do
wait -n || exit 1 # if one of the background jobs failed, abort
[[ "$(jobs)" ]] && break # exit this loop if no more jobs
done
완전히 테스트되지 않았습니다. jobs
이것이 비대화형 쉘에서 예상대로 작동하는지 잘 모르겠습니다 .
답변2
여기에는 몇 가지 질문이 있습니다.
- 하위 셸의 명령이 실패하면 전체 스크립트가 중단됩니다.
- 발생하는 오류에 대한 가시성을 높입니다.
두 번째부터 시작하겠습니다. 이 질문에는 답변의 시드가 포함되어 있습니다. 오류는 기록되지만 로그 내용은 사용자에게 명확하지 않습니다. 따라서 오류를 임시 로그 파일에 기록하고 마지막에 표시합니다.
서비스 = ( 계정 서비스 알림 서비스 이벤트 서비스 소켓 서비스 채팅 서비스 웹 애플리케이션 ) 오류 파일=$(mktemp) "${services[@]}"의 for s; ( 세트이; CD "$s" 자식 당겨 || { echo "$s" >> "$errfile" 1번출구 } 에코 "$cmd" | )& 잠 1 완벽한 기다리다 if [ -s "$errfile" ] 그 다음에 echo "다음 서비스에 오류가 있습니다:" 고양이 "$errfile" 필리핀 제도 rm -f "$errfile"
문제 #1을 해결하는 가장 간단한 방법은 서브셸의 코드를 주기적으로 확인 [ -s "$errfile" ]
하고 문제가 발생하면 자체를 중단하는 것입니다. 보다 야심 찬 접근 방식은 기본(상위) 프로세스가 하위 프로세스의 PID를 추적하고 해당 프로세스에 신호를 보내도록 하는 것입니다. 가 없는지 확실하지 않습니다 wait -n
. (아마도 오류가 있는 자식이 부모에게 신호를 보내서 wait
. )