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

なぜならゼロ値を生成するすべての算術演算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 $?"

関連情報