为什么要减少shell变量作为未使用参数的副作用



最近在尝试调试一些网络代码时,我遇到了一个重试循环,如下所示:

while [ ${DELAY} -gt 0 ] ; do
doSomething
sleep 1
: $((DELAY -= 1))
done

现在我明白了它在做什么,我只是不确定为什么会这样做。bash-builtinsman页面状态:

: [arguments]无效;该命令除了扩展参数和执行任何指定的重定向之外,什么都不做。

既然只需((DELAY -= 1))就可以简单地修改bash中的变量,那么它为什么要这样做作为将结果提供给:命令的副作用呢?

这实际上与自动错误处理有关。因为调用此代码的脚本是在set -e下运行的,所以一旦出现错误,它将立即退出。

您可以使用以下脚本看到效果:

set -e
DELAY=10
while [ ${DELAY} -gt 0 ] ; do
echo Delaying $DELAY
((DELAY -= 1))
done
echo Finishing

使用该脚本,您永远不会看到Finishing行,因为"((DELAY -= 1))的退出代码通常是0,但当值降至零时是1。这意味着运行中的set -e将在该点停止脚本。

使用: $((DELAY -= 1))始终具有零退出代码,因此不会过早退出。

这种退出代码行为在以下情况下最为明显:

DELAY=10
while [ ${DELAY} -gt 0 ] ; do
echo Delaying $DELAY
# Select one of these below, comment the other:
((DELAY -= 1))
#: $((DELAY -= 1))
echo "   Exit code $?"
done
echo Finishing

并且改变哪一行用于递减CCD_ 14。

如果set -x正在运行,则会回显: 3: 2: 1的序列。

这是一种"廉价"的方法,既可以递减,也可以选择性地回声结果。

最新更新