Bashスクリプトエラー:整数式が必要です


13

私はかなり奇妙な問題を抱えています。複数のサーバーでスクリプト(Bash)を実行していますが、いずれかのサーバーで動作しなくなりました(他のすべてのサーバーで完全に正常に動作します)。

スクリプトの問題部分は次のとおりです(私は自分で書きませんでした。すべてのクレジットは「リッチ」になります)(http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios- and-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

完全なエラーメッセージ:

./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

さらに情報が必要な場合はお知らせください。できるだけ早く提供するよう努めます。

すべての入力に感謝します:)

回答:


5

ご提供いただいたリンクから、次の行が表示されます。

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)

@Graemeのコメントに従って、上記の行を下に変更します。

result=$(echo "$used / $total * 100" |bc -l)

さて、上記の行を追加した後、resultto の出力を以下のように整数に変更する必要があります。

result1=${result/.*}

エラーが発生したマシンの1つで、この出力は整数ではないと思います。そのような場合を処理できるように、結果の出力を整数に変換するだけです。を計算した後、次の行を追加しますresult

result1=${result/.*}

そして、ループ内でresult変数名を変更する代わりに、エラーは発生しません。result1if

cut -c -2エラーの原因は主に最初の2文字のみをカットしているためだと思われます。結果に1文字しか含まれていない場合はどうなりますか?resultがの1.23456場合、上記のカットの結果1.として、result明らかにinteger expectedエラーの原因となっている値が得られます。

残りのサーバーで正常に機能している理由は、result変数の桁が1桁しかないケースに遭遇していないためです。結果が1桁の変数(上記の例で述べたようなもの)である場合、残りのサーバーでも失敗する可能性が非常に高くなります。


${result%%.*}ここで小数点を削除する正しい展開になります。ただしcut -c -2、これは100以上の数でも問題を引き起こすため、完全に削除する方が安全です。
グレアム14

@Graeme、私はそれを見逃した。その行に変更を加える必要がありました:)
ラメシュ14

6

物事の見た目でresultは、.bashがそのように認識しないようにするために、変数の後に変数があります。次のことを行うだけでエラーを再現できます。

[ 7. -gt 1 ]

質問にスクリプトをさらに追加する場合、これがどこから来たのかを提案できます。

更新

完全なスクリプトを見て、次の行を置き換えるだけです。

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)

と:

result=$(( 100 * used / total ))

Since usedtotal整数であり、bash音符が、算術整数ない乗算のシフトは、最初に100です。または、正しい丸めを保証する場合(コンピューティングの「整数除算」は常に効果的に切り捨てられます):

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

これにより、に末尾のドットがないことが保証されresultます。使用するアプローチcutは、10〜99の範囲の結果に対してのみ有効であるため、あまり良い考えではありません。result0から9(あなたの場合のように)および99を超える数値では失敗します。

更新2

下記のステファンさんのコメント@しきい値と比較するとき、あなたはラウンドダウンに優れています。これを考慮すると、質問のスニペットに別の小さなエラーがあります-とに使用される比較の不一致に注意しwarn_levelてくださいcritical_level。の比較warn_levelは正しいですがcritical_level-le(より小さい)ではなく(より小さいか等しい)を使用し-ltます。がいつ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

-geこれらの場合は、到達に暗示されているので、テストは、冗長であるelif/ elseので、除去されています。


2
しかし、しきい値に対してチェックするために、あなたはラウンドしたくないアップ。警告しきい値が50の場合、49.6でも問題ありresult=$(( 100 * $used / $total ))ません。それで問題ありません。
ステファンシャゼル14

0

だから、私はまったくawkうまく使用する方法を知りません。しかし、リンクしたスクリプトで何が起こっているかは多くのナンセンスであり、次のようなものが機能するはずであることを知っています。すみません、これを完璧に書き出すことはできませんが、あなたはすでに電話をかけているので、awk2回思われますが、あなたはこのようなものを使うべきです。

_chkmem() { return $( 
    free -m | grep "buffers/cache"
        awk '{ 
        percent = ( $3 / ( $3 + $4 ) ) * 100     
        warn = '"${warnlevel?No warning level specified!}"' < percent ? WARNING : OK
        crit = '"${critical?No critical level specified!}"' < percent ? CRITICAL : $warn
        print "Mem $crit : $percent% used"
        if ( $crit != OK ) exit 1
    }')
}

_chkmem || exit 1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.