2015-09-25 75 views
-1
#!/bin/sh 
count=0 
foo=0 

echo "foo is $foo" 

while [ "$foo" -eq 0 ] && [ "$count" -lt 10 ]; do 
    echo "inside while: foo is $foo" 
    count=$((count+1)) 
    foo=1 
done 

echo "after while" 

你会期望上面的脚本输出以下内容,对吧?我的壳破了吗?

foo is 0 
inside while: foo is 0 
after while 

而且它在很多其他机器上都有,就像你自己的机器一样。但不是我的...

foo is 0 
inside while: foo is 0 
inside while: foo is 1 
inside while: foo is 1 
... (infinite loop) 

我做错了什么,或者我错过了明显的东西?

在这个(坏掉的)机器上,如果我调整while有条件使用“过时”-a操作符,它会“修复”问题(不管它是什么)。为什么?

+1

要调查的第一件事是什么样的shell和版本是你的/ bin/sh? - 然后调查在该shell启动时运行的任何启动脚本。 – nos

+0

......这就是说 - 正如我在你的其他问题中所建议的那样,你会考虑使用'set -x'来记录运行时的单个命令吗?实际上,我可以考虑在脚本中隐藏字符的可能方式可能会导致此行为,并且使用'set -x'可以清楚地表明是否是这种情况。 –

+0

(从'-eq'切换到'=' - 因此,使基于字符串的比较而不是数字 - 实际上会使您更加坚固,以对抗我怀疑的故障模式)。 –

回答

1

假设您的脚本文本中没有隐藏字符(假设我建议在验证中付出一些努力!),这确实表现出与POSIX sh标准相反的行为。

n1 -eq n2 - 如果整数n1和n2在代数上相等,则为真;否则,是错误的。

值得注意的是,这并没有规定或保证如果两个参数实际上不是一个整数会发生什么;例如,如果它是将是的整数,但在结尾处具有回车符或其他非打印字符。

其他项目的尝试,依次是:

  • 运行sh -x yourscript,并期待在运行循环的时候叫test确切的论据。同时确定&&链中的第二次测试是否完全运行。
  • 您的运营商改变从-eq=,运行一个字符串比较,而不是数值比较(从而确保包含隐藏字符的任意字符串将无法与字符串0成功地比较,而不是在这种情况下,依靠未定义行为) 。
  • [ "$foo" -eq 0 ]替换为false,并确保循环的内容不会运行(因此可以理智地检查shell实现的某些其他核心部分)。