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 个作业。
调用之前的算术测试对于每个能被 20 整除wait
的值都为真,即对于、等。$i
$i = 20
$i = 40
用于算术扩展的语法$[ ... ]
是过时的bash
语法,现在已经编写了$(( ... ))
(可移植的)。该%
运算符是普通的模运算符。
除了使用过时的语法之外,shell 还可能存在引用问题。变量扩展$DEST
and$M
和also$i
缺少引号,两个命令替换也是如此。如果其中任何一个包含或生成存在于$IFS
(默认情况下,空格、制表符、换行符)中的字符,您可能会认为脚本会失败或至少行为不当。
wait
该代码在循环后还缺少final ,以正确等待循环启动的最后几个作业中的任何一个。如果可以保证循环将发生,则不需要这样做总是运行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