錯誤:需要整數表達式

錯誤:需要整數表達式

我編寫了一個腳本來確定伺服器上的平均負載,如下所示:

#!/bin/bash

loadavg=`top -b -n1 | grep -i load | awk -F, '{print$4}'| awk -F: '{print $2}'`

if [ "${loadavg}" -le  1 ]
then
echo "OK - Load Average = ${loadavg} | Load_Average=${loadavg}"
exit 0;
elif [ "${loadavg}" -gt 1 ] && [ "${loadavg}" -le 2 ]
then
echo "WARNING - Load Average = ${loadavg} | Load_Average=${loadavg}"
exit 1;
elif [ "${loadavg}" -gt 2 ]
then
echo "CRITICAL - Load Average = ${loadavg} | Load_Average=${loadavg}"
exit 2;
else
echo "UNKNOWN - Load Average = NaN | Load_Average=NaN"
fi

執行腳本時,顯示以下錯誤:

./loadavg.sh
./loadavg.sh: line 5: [:  0.06: integer expression expected
./loadavg.sh: line 9: [:  0.06: integer expression expected
./loadavg.sh: line 13: [:  0.06: integer expression expected
UNKNOWN - Load Average = NaN | Load_Average=NaN

答案1

bashksh93(與or zsh1相反)不能進行浮點運算。awk不過可以,所以你可以在 中完成整個事情awk

另外,您不需要使用top(並等待 1 秒)來獲取負載。獲取負載的規範方法是來自uptime.

uptime | awk '{load=+$(NF-2)}
  load > 2 {print "CRITICAL: " load; exit 2}
  load > 1 {print "WARNING: " load; exit 1}
  {print "OK: " load; exit 0}
  END {if (!NR) {print "UNKNOWN"; exit 3}'
exit

1不過zsh,您需要使用(( loadavg > 2 ))代替[ "$loadavg" -gt 2 ]語法來比較非整數

答案2

top -b -n1 | grep -i load | awk -F, '{print$4}'| awk -F: '{print $2}'返回nada,因此你的錯誤。

答案3

您的loadavg值為空,會導致語法錯誤[

$ top -b n1 | grep -i load | awk -F, '{print$4}'| awk -F: '{print $2}'
<blank line here>

您必須將其更改為:

$ top -b n1 | grep -i load | awk -F, '{print$4}'| awk -F: '{print $1}'
 0.24

但是,您應該在腳本中使用更新的測試,它可以解決這個問題:

$ [[ "" -gt 1 ]] || echo "OK"
OK

與較舊的[

$ [ "" -gt 1 ] || echo "OK"
bash: [: : integer expression expected
OK

更新

bash無法處理浮點數,因此您的比較(即使使用新的測試[[..]])將顯示錯誤。

您可以使用其他工具來完成此任務,例如bcawk...

例子:

$ [[ $(echo "3 > 1" | bc -l) == 1 ]] && echo OK
OK
$[[ $(echo "3 < 1" | bc -l) == 1 ]] || echo Not OK
Not OK

答案4

首先,運作top比僅僅取得「正常運作時間」更昂貴。

$ uptime
 16:15:38 up 6 days, 23:22, 23 users,  load average: 0.99, 0.82, 0.70

其次,正如 @Stéphane Chazelas 所提到的,bash 不喜歡浮點運算。

$ [[ "0.1" -lt 1 ]] 
bash: [[: 0.1: syntax error: invalid arithmetic operator (error token is ".1")

幸運的是,bash 擴充可以解決這個問題。從男人狂歡:

   ${parameter%word}
   ${parameter%%word}
         Remove matching suffix pattern.  The word is expanded to produce a pattern just as in pathname expansion.   If
         the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is
         the expanded value of parameter with the shortest matching pattern (the ``%'' case) or  the  longest  matching
         pattern  (the  ``%%'' case) deleted.  If parameter is @ or *, the pattern removal operation is applied to each
         positional parameter in turn, and the expansion is the resultant list.  If parameter is an array variable sub-
         scripted  with  @  or *, the pattern removal operation is applied to each member of the array in turn, and the
         expansion is the resultant list.

因此用「%.*」去掉小數部分變得非常容易

$ la=`uptime | sed 's/.*average: \([0-9\.]*\).*/\1/'`
$ if [ ${la%.*} -lt 1 ]; then echo "OK - Load average is $la"; fi
OK - Load average is 0.42

相關內容