Bash 脚本错误:应为整数表达式

Ada*_*inn 15 bash

我遇到了一个相当奇怪的问题,我在多台服务器上运行一个脚本 (Bash),但它在其中一台服务器上停止工作(在所有其他服务器上工作得很好)。

这是脚本的问题部分:(我不是自己写的,所有学分都归“Rich”所有)(http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios-和-nrpe/ )

    if [ "$result" -lt "$warn_level" ]; then     #Line 56
    echo "Memory OK. $result% used."
    exit 0;
elif [ "$result" -ge "$warn_level" ] && [ "$result" -le "$critical_level" ]; then  #Line 59
    echo "Memory WARNING. $result% used."
    exit 1;
elif [ "$result" -gt "$critical_level" ]; then   #Line 62
    echo "Memory CRITICAL. $result% used."
    exit 2;
fi
Run Code Online (Sandbox Code Playgroud)

完整的错误信息:

./check_memory.sh: Line 56: [: 7.: integer expression expected

./check_memory.sh: Line 59: [: 7.: integer expression expected

./check_memory.sh: Line 62: [: 7.: integer expression expected
Run Code Online (Sandbox Code Playgroud)

如果您需要更多信息,请告诉我,我会尽快提供。

感谢所有输入:)

Gra*_*eme 6

从表面上看,您的result变量.在数字之后有一个,使 bash 无法识别它。您只需执行以下操作即可重现错误:

[ 7. -gt 1 ]
Run Code Online (Sandbox Code Playgroud)

如果您在问题中添加更多脚本,|我可以建议这可能来自何处。

更新

查看完整的脚本,我只想替换以下行:

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)
Run Code Online (Sandbox Code Playgroud)

和:

result=$(( 100 * used / total ))
Run Code Online (Sandbox Code Playgroud)

由于usedtotal是整数并进行bash整数算术,但请注意乘法的移位为 100 到开头。或者,如果您想确保正确舍入(计算中的“整数除法”总是有效地向下舍入):

result=$( printf '%.0f' $(echo "$used / $total * 100" | bc -l) )
Run Code Online (Sandbox Code Playgroud)

这将确保result. 使用的方法cut不是一个很好的主意,因为它仅对 10-99 范围内的结果有效。对于result0-9(如您的情况)以及 99 以上的数字,它将失败。

更新 2

下面@Stephane 的评论中,与阈值相比,您最好向下取整。考虑到这一点,问题中的代码片段还有另一个小错误 - 请注意用于warn_level和 的比较之间的不一致critical_level。的比较warn_level是正确的,但critical_level使用-le(lesser or equal) 而不是-lt(just lesser)。考虑何时result略大于critical_level-critical_level即使应该(并且如果使用-lt比较,也会),它将被舍入为并且不会触发严重警告。

也许不是什么大问题,但这里是更正后的代码:

if [ "$result" -lt "$warn_level" ]; then
  echo "Memory OK. $result% used."
  exit 0;
elif [ "$result" -lt "$critical_level" ]; then
  echo "Memory WARNING. $result% used."
  exit 1;
else
  echo "Memory CRITICAL. $result% used."
  exit 2;
fi
Run Code Online (Sandbox Code Playgroud)

这些-ge测试也是多余的,因为这些情况在到达elif/ 时是隐含的else,因此已被删除。

  • 但是,要检查阈值,您不想舍入 _up_。如果警告阈值为 50,49.6 仍然应该是 _OK_。所以 `result=$(( 100 * $used / $total ))` 应该没问题。 (2认同)

Ram*_*esh 5

从您提供的链接中,我看到以下行。

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)
Run Code Online (Sandbox Code Playgroud)

根据@Graeme 的评论,将上面的行更改为下面的行。

result=$(echo "$used / $total * 100" |bc -l)
Run Code Online (Sandbox Code Playgroud)

现在,添加上述行后,我们必须将输出更改result为整数,如下所示。

result1=${result/.*}
Run Code Online (Sandbox Code Playgroud)

我猜在发生错误的其中一台机器中,此输出不是整数。只需将 result 的输出转换为整数,以便您可以处理此类情况。计算后添加以下行result

result1=${result/.*}
Run Code Online (Sandbox Code Playgroud)

而不是在循环内部result更改变量名称,并且不会发生错误。result1if

我怀疑,cut -c -2错误的属性主要是因为它只剪切了前 2 个字符。如果结果只有一个字符怎么办?假设如果 result 是1.23456,则上述切割将导致1.作为result明显导致integer expected错误原因的值。

它在其余服务器中工作正常的原因是它没有遇到result变量只有一位数的情况。如果结果是一个数字变量(就像我在上面的例子中提到的那样),它也很可能在其余服务器中失败。