Erreur de script bash: expression entière attendue

13

J'ai un problème assez étrange, j'exécute un script (Bash) sur plusieurs serveurs et il a cessé de fonctionner sur l'un des serveurs (fonctionne parfaitement bien sur tous les autres serveurs).

Voici la partie problématique du script: (je ne l'ai pas écrit moi-même, tous les crédits vont à "Rich") ( 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

Message d'erreur complet:

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

Si vous avez besoin de plus d'informations, faites le moi savoir et j'essaierai de vous les fournir le plus rapidement possible.

Appréciez toutes les entrées :)

Adalsteinn
la source

Réponses:

5

Du lien que vous avez fourni, je vois la ligne ci-dessous.

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

Selon le commentaire de @ Graeme, changez la ligne ci-dessus en dessous.

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

Maintenant, après avoir ajouté la ligne ci-dessus, nous devons changer la sortie de l' resultentier comme ci-dessous.

result1=${result/.*}

Je suppose que dans l'une des machines où l'erreur se produit, cette sortie n'est pas un entier. Convertissez simplement la sortie du résultat en entier afin de pouvoir gérer de tels cas. Ajoutez la ligne ci-dessous après avoir calculé le result.

result1=${result/.*}

Et au lieu de resultchanger les noms de variables comme result1à l'intérieur des ifboucles, et l'erreur ne se produira pas.

Je soupçonne que les cut -c -2attributs de l'erreur sont principalement dus au fait qu'il coupe uniquement les 2 premiers caractères. Et si le résultat n'a qu'un seul caractère? Supposons que si le résultat est 1.23456, la coupe ci-dessus se traduira 1.par la valeur pour resultlaquelle est évidemment la cause de l' integer expectederreur.

La raison pour laquelle cela fonctionne bien dans les serveurs restants est qu'il n'a pas rencontré de cas où la resultvariable n'a qu'un seul chiffre. Il est également très probable qu'il échoue dans les serveurs restants si le résultat est une variable à un chiffre (quelque chose comme je l'ai mentionné dans l'exemple ci-dessus).

Ramesh
la source
${result%%.*}serait l'expansion correcte pour supprimer le point décimal ici. Mais notez que cut -c -2cela entraînera également des problèmes avec des nombres de 100 ou plus, il est donc plus sûr de le supprimer complètement.
Graeme
@Graeme, ça m'a manqué. J'aurais dû faire les changements dans cette ligne :)
Ramesh
6

Au vu des choses, votre resultvariable a un .dedans après que le nombre faisant bash ne le reconnaisse pas comme tel. Vous pouvez reproduire l'erreur en faisant simplement:

[ 7. -gt 1 ]

Si vous ajoutez plus de script à votre question, | je peux suggérer d'où cela pourrait provenir.

Mise à jour

En regardant le script complet, je remplacerais simplement la ligne:

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

Avec:

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

Puisque usedet totalsont des entiers et bashfait de l'arithmétique entière, notez bien que le décalage de la multiplication soit de 100 au début. Ou si vous voulez assurer un arrondi correct (la «division entière» dans l'informatique arrondit toujours efficacement):

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

Cela garantira qu'il n'y a pas de points de fuite result. L'approche à l'aide cutn'est pas une très bonne idée car elle n'est valable que pour un résultat compris entre 10 et 99. Il échouera pour un resultde 0 à 9 (comme dans votre cas) et également des nombres supérieurs à 99.

Update 2

D'après le commentaire de @ Stephane ci - dessous , il vaut mieux arrondir en comparant avec les seuils. Compte tenu de cela, il y a une autre petite erreur avec l'extrait de code dans la question - notez l'incohérence entre les comparaisons utilisées pour le warn_levelet le critical_level. Les comparaisons pour warn_levelsont correctes, mais critical_levelutilise -le(moindre ou égal) au lieu de -lt(juste moindre). Considérez quand resultest légèrement plus grand que critical_level- il sera arrondi à critical_levelet ne déclenchera pas l'avertissement critique même s'il le devrait (et le ferait si une -ltcomparaison était utilisée).

Peut-être pas beaucoup de problème, mais voici le code corrigé:

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

Les -getests sont également redondants car ces cas sont implicites pour atteindre le elif/ else, ils ont donc été supprimés.

Graeme
la source
2
Cependant, pour vérifier par rapport aux seuils, vous ne voulez pas arrondir jusqu'à . 49,6 devrait toujours être OK si le seuil d'avertissement est 50. Cela result=$(( 100 * $used / $total ))devrait donc être très bien.
Stéphane Chazelas
0

Je ne sais donc pas awktrès bien comment l'utiliser . Mais je sais que ce qui se passe dans le script que vous avez lié est beaucoup de non-sens et que quelque chose comme ce qui suit devrait fonctionner. Je suis désolé, je ne peux pas écrire cela parfaitement bien, mais puisque vous appelez déjà awk- deux fois il semble - vous devriez utiliser quelque chose comme ça.

_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
la source