Bash

Shell 在 for 循環中的算術表達式處靜默退出

  • June 23, 2017

我已經為 ssh 遠端主機編寫了一個腳本,執行命令,將輸出保存到文件,並檢查輸出。但是(( success++ ))當迭代 array 中的第一項時,它總是在 line 處靜默退出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))"

一個簡單的例子應該解釋為什麼:

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

原因是任何產生零數值的算術運算都會返回 1。我不知道該說什麼——Bash 已經足夠讓全世界知道了。

這是-e設置的結果。退出程式碼為 1(非零)的任何命令都將觸發退出。

這個腳本工作正常:

#!/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 $?"

引用自:https://unix.stackexchange.com/questions/372408