i=0
while read M; do
((cd $DEST/cfg/puppet/modules/$M || exit 1
[ -d .git ] && echo -n "$M: " && git pull) 2>&1 | prep $(printf %04d: $i) puppet/modules/$M) &
i=$[i+1]
[ $[ i % 20 ] = 0 ] && wait
done < $(dirname "$0")/modules-puppet.txt
[ $[ i % 20 ] = 0 ] && wait
上記のbashスニペットでその行が何をしているかを説明できる人はいますか?
答え1
このコードはループ内で多くのバックグラウンドタスクを生成します。これらの各ジョブは、git
および関連するコマンドを実行しますpuppet
。
これらのタスクは非常に迅速に生成される可能性があり、システムに負担をかけないために、コードは現在実行中のすべてのバックグラウンドタスクが完了するのを待つ前にそのタスクのうち20だけを実行します。wait
続行する前に、スクリプトがすべてのバックグラウンドジョブが完了するのを待つようにして別の20個のジョブを作成するのは正しい呼び出しです。
呼び出し前の算術テストは、wait
20で割ることができるすべての値、つまりtrueです。$i
$i = 20
$i = 40
算術拡張に使用される構文は廃止され、移植$[ ... ]
可能に作成されましたbash
。$(( ... ))
この%
演算子は一般的なモジュロ演算子です。
古い構文の使用に加えて、シェルには引用の問題があるかもしれません。変数の拡張$DEST
と2つ$M
の$i
コマンドの置換と同様に、引用符がありません。これらのいずれか$IFS
(デフォルトでは空白、タブ、改行)の文字を含めるか生成する場合、スクリプトが失敗するか、少なくとも誤動作することを期待できます。
wait
コードには、ループによって開始された最後のいくつかの操作を適切に待機するためのループ以降の最終コードもありません。ループが発生することを保証できる場合は、これを行う必要はありません。いつも実行n*20
時間(一部整数の場合n
)
答え2
$[ i % 20 ]
オペレーションの拡張により、減価償却が行われます$(())
。
i % 20
算術演算「モジュロ」です。
[ $[ i % 20 ] = 0 ]
条件文であり、標準ではなく、読みやすい別の構文です。 Posixは次のようになります。
if [ "$(( i % 20 ))" -eq 0 ]
&& wait
前のコマンドの戻りコードが0の場合にのみ実行されます。
[ $[ i % 20 ] = 0 ] && wait
0に等しい場合は、モジュラスをテストしますwait
。
私の代替完全な構文は次のとおりです。
if [ "$(( i % 20 ))" -eq 0 ] ; then
wait
fi