Bash-Skriptfehler: Integer-Ausdruck erwartet

13

Ich habe ein ziemlich seltsames Problem, ich führe ein Skript (Bash) auf mehreren Servern aus und es funktioniert nicht mehr auf einem der Server (funktioniert einwandfrei auf allen anderen Servern).

Hier ist der problematische Teil des Skripts: (Ich habe es nicht selbst geschrieben, alle Credits gehen an "Rich") ( http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios-) und-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

Komplette Fehlermeldung:

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

Wenn Sie weitere Informationen benötigen, lassen Sie es mich wissen und ich werde versuchen, diese so schnell wie möglich bereitzustellen.

Schätzen Sie alle Eingaben :)

Adalsteinn
quelle

Antworten:

5

Über den von Ihnen angegebenen Link sehe ich die folgende Zeile.

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

Ändern Sie gemäß @ Graemes Kommentar die obige Zeile nach unten.

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

Nachdem wir die obige Zeile hinzugefügt haben, müssen wir die Ausgabe der resultGanzzahl wie folgt ändern .

result1=${result/.*}

Ich vermute, in einer der Maschinen, in denen der Fehler auftritt, ist diese Ausgabe keine ganze Zahl. Konvertieren Sie einfach die Ausgabe von result in integer, damit Sie solche Fälle behandeln können. Fügen Sie die folgende Zeile hinzu, nachdem Sie die berechnet haben result.

result1=${result/.*}

Anstatt resultdie Variablennamen wie result1in den ifSchleifen zu ändern , tritt der Fehler nicht auf.

Ich vermute, die cut -c -2Attribute zum Fehler meistens, da es nur die ersten 2 Zeichen schneidet. Was ist, wenn das Ergebnis nur ein Zeichen hat? Angenommen, wenn result ist 1.23456, ergibt sich der obige Schnitt 1.als der Wert, für resultden offensichtlich die integer expectedFehlerursache ist.

Der Grund, warum es auf den verbleibenden Servern einwandfrei funktioniert, ist, dass es keinen Fall gegeben hat, in dem die resultVariable nur eine Ziffer hat. Es ist sehr wahrscheinlich, dass auch auf den verbleibenden Servern ein Fehler auftritt, wenn das Ergebnis eine einstellige Variable ist (wie im obigen Beispiel erwähnt).

Ramesh
quelle
${result%%.*}wäre die richtige erweiterung um hier den dezimalpunkt zu entfernen. Beachten Sie jedoch, dass dies cut -c -2auch zu Problemen mit Zahlen von 100 oder mehr führt. Es ist daher sicherer, das Programm vollständig fallen zu lassen.
Graeme
@Graeme, das habe ich verpasst. Ich hätte die Änderungen in dieser Zeile vornehmen sollen :)
Ramesh
6

Wie es aussieht, enthält Ihre resultVariable .nach der Zahl, die die Bash auslöst, ein, das sie nicht als solches erkennt. Sie können den Fehler reproduzieren, indem Sie einfach Folgendes tun:

[ 7. -gt 1 ]

Wenn Sie Ihrer Frage mehr Skript hinzufügen, kann ich vorschlagen, woher dies kommen könnte.

Aktualisieren

Wenn ich mir das vollständige Skript anschaue, würde ich einfach die folgende Zeile ersetzen:

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

Mit:

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

Da usedund totalsind ganze Zahlen und bashGanzzahlarithmetik, beachten Sie jedoch, dass die Verschiebung der Multiplikation 100 zu Beginn ist. Oder wenn Sie eine korrekte Rundung sicherstellen möchten (die Ganzzahldivision rundet beim Rechnen immer effektiv ab):

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

Dadurch wird sichergestellt, dass keine nachgestellten Punkte enthalten sind result. Die Verwendung des Ansatzes cutist keine sehr gute Idee, da er nur für Ergebnisse im Bereich von 10 bis 99 gilt. Es wird für eine resultvon 0-9 (wie in Ihrem Fall) und auch Zahlen über 99 fehlschlagen .

Update 2

Nach dem Kommentar von @ Stephane ist es besser, beim Vergleich mit Schwellenwerten abzurunden. In Anbetracht dessen gibt es einen weiteren kleinen Fehler mit dem Snippet in der Frage - beachten Sie die Inkonsistenz zwischen den Vergleichen, die für das warn_levelund das verwendet werden critical_level. Die Vergleiche für warn_levelsind korrekt, critical_levelverwenden jedoch -le(weniger oder gleich) anstelle von -lt(nur weniger). Überlegen Sie, wann resultetwas größer ist als critical_level- es wird abgerundet, critical_levelund die kritische Warnung wird nicht ausgelöst, obwohl dies der Fall sein sollte (und dies würde der Fall sein, wenn ein -ltVergleich verwendet würde).

Vielleicht kein großes Problem, aber hier ist der korrigierte Code:

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

Die -geTests sind auch überflüssig, da diese Fälle beim Erreichen des elif/ impliziert sind else, also entfernt wurden.

Graeme
quelle
2
Um jedoch zu prüfen , gegen Schwellenwerte, Sie wollen nicht runden oben . 49.6 sollte immer noch in Ordnung sein, wenn die Warnschwelle 50 ist. Sollte also result=$(( 100 * $used / $total ))in Ordnung sein.
Stéphane Chazelas
0

Daher weiß ich überhaupt nicht, wie ich es richtig anwenden soll awk. Aber ich weiß, dass das, was in dem von Ihnen verlinkten Skript vor sich geht, eine Menge Unsinn ist und dass etwas wie das Folgende funktionieren sollte. Es tut mir leid, dass ich das nicht perfekt ausschreiben kann, aber da Sie bereits anrufen awk- zweimal, so scheint es - sollten Sie so etwas verwenden.

_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
mikeserv
quelle