for 루프의 산술 표현식에서 쉘이 자동으로 종료됩니다.

for 루프의 산술 표현식에서 쉘이 자동으로 종료됩니다.

원격 호스트에 SSH로 접속하는 스크립트를 작성하고, 명령을 실행하고, 출력을 파일에 저장하고, 출력을 검사했습니다. 그러나 (( success++ ))배열의 첫 번째 항목을 반복할 때 항상 자동으로 종료됩니다 workers. (( success++ ))로 바꾸면 echo "process $worker"제대로 작동하고 모든 호스트를 인쇄합니다. 나는 무엇이 잘못되었는지 모른다.

#!/bin/bash

set -x
set -e
workers=('host-1' 'host-2' 'host-3')

output_dir=$(mktemp -d)

for worker in ${workers[@]}; do
  ssh $worker '
    echo abc
    echo OK
  ' > "$output_dir/$worker" &
done

echo "waiting..."
sleep 3
wait

success=0
regexp='OK$'
for worker in ${workers[@]}; do
  output=`cat "$output_dir/$worker"`
  if [[ "$output" =~ $regexp ]]; then
    (( success++ ))
  fi
done

echo "Total ${#workers[@]}; success: $success; failure: $((${#workers[@]} - success))"

답변1

간단한 예를 통해 그 이유를 설명할 수 있습니다.

$ ((success++))
$ echo $?
1

왜냐하면0 값을 생성하는 모든 산술 연산1을 반환.무슨 말을 해야 할지 모르겠습니다. Bash는 세상에 충분한 함정을 가져왔습니다.

답변2

설정한 결과입니다 -e. 종료 코드가 1(0이 아님)인 명령은 종료를 트리거합니다.

이 스크립트는 잘 작동합니다.

#!/bin/bash
(( success++))
echo "Still going 1 $success"

이것은 아니다

#!/bin/bash
set -e
(( success++))
echo "Still going 1 $success"

해결책

가장 쉬운 방법은 set -e실을 제거하는 것입니다.

이것이 옵션이 아닌 경우 다음을 사용하십시오.

(( ++success ))

다른 대안:

#!/bin/bash

set -e
success=0
success=$(( success+1 ))
echo "still going 1 $success"

success=0
(( success=success+1 ))
echo "still going 2 $success"

success=0
(( success+=1 ))
echo "still going 3 $success"

success=0
(( ++success ))
echo "still going 4 $success"

success=0
(( success++ ))
echo "still going 5 $success"

옵션 번호 5에만 종료 코드가 1입니다.

기타(모든 변수 값에 대한 더 복잡한 솔루션 a).
첫 번째로 사용되는 것은(POSIX) :내장 콜론( )POSIX와 호환되게 만드세요.

: $(( a+=1 ))        ; echo "6 $a $?"   ## Valid Posix
   (( a++ )) || true ; echo "7 $a $?"
   (( a++ )) || :    ; echo "8 $a $?"
   (( a++ , 1 ))     ; echo "9 $a $?"
   (( a++ | 1 ))     ; echo "10 $a $?"

관련 정보