Error de script Bash: se espera una expresión entera

13

Tengo un problema bastante extraño, estoy ejecutando un script (Bash) en varios servidores y dejó de funcionar en uno de los servidores (funciona perfectamente bien en todos los demás servidores).

Aquí está la parte problemática del script: (No lo escribí yo mismo, todos los créditos van a "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

Mensaje de error completo:

./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 necesita más información, avíseme y trataré de proporcionarla lo más rápido posible.

Agradezco todas las entradas :)

Adalsteinn
fuente

Respuestas:

5

Desde el enlace que proporcionó, veo la siguiente línea.

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

Según el comentario de @ Graeme, cambie la línea anterior a la siguiente.

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

Ahora, después de agregar la línea anterior, tenemos que cambiar la salida del resultentero al siguiente.

result1=${result/.*}

Supongo que en una de las máquinas donde se produce el error, esta salida no es un número entero. Simplemente convierta la salida del resultado a entero para que pueda manejar tales casos. Agregue la siguiente línea después de calcular el result.

result1=${result/.*}

Y en lugar de resultcambiar los nombres de las variables como result1dentro delif bucles, no se producirá el error.

Sospecho que los cut -c -2atributos del error se deben principalmente a que solo corta los primeros 2 caracteres. ¿Qué pasa si el resultado tiene un solo personaje? Supongamos que si el resultado es 1.23456, el corte anterior dará como resultado 1.el valor pararesult que obviamente es la causa del integer expectederror.

La razón por la que funciona bien en los servidores restantes es porque no ha encontrado un caso en el que la resultvariable tenga un solo dígito. Es muy probable que también falle en los servidores restantes si el resultado es una variable de un solo dígito (algo como lo mencioné en el ejemplo anterior).

Ramesh
fuente
${result%%.*}sería la expansión correcta para eliminar el punto decimal aquí. Pero tenga en cuenta que cut -c -2también causará problemas con números de 100 o más, por lo que es más seguro soltarlo por completo.
Graeme
@Graeme, me perdí eso. Debería haber hecho los cambios en esa línea :)
Ramesh
6

Por el aspecto de las cosas, su resultvariable tiene un valor .después del número que hace que bash no lo reconozca como tal. Puede reproducir el error simplemente haciendo:

[ 7. -gt 1 ]

Si agrega más de la secuencia de comandos a su pregunta, | puedo sugerir de dónde podría provenir.

Actualizar

Mirando el guión completo, simplemente reemplazaría la línea:

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

Con:

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

Dado que usedy totalson enteros y basharitmética de enteros, tenga en cuenta que el desplazamiento de la multiplicación sea 100 al principio. O si desea garantizar el redondeo correcto (la 'división entera' en informática siempre redondea de manera efectiva):

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

Esto asegurará que no haya puntos finales result. El enfoque que utiliza cutno es una muy buena idea, ya que solo es válido para el resultado en el rango 10-99. Fallará por unresult 0-9 (como en su caso) y también números superiores a 99.

Actualización 2

Según el comentario de @ Stephane a continuación , es mejor redondear hacia abajo cuando se compara con los umbrales. Considerando esto, hay otro pequeño error con el fragmento en la pregunta: observe la inconsistencia entre las comparaciones utilizadas para el warn_levely el critical_level. Las comparaciones para warn_levelson correctas, pero critical_levelusan -le(menor o igual) en lugar de -lt(solo menor). Considere cuándo resultes un poco más grande que critical_level: se redondeará hacia abajo critical_levely no activará la advertencia crítica aunque debería (y lo haría si-lt se usara comparación).

Quizás no sea un gran problema, pero aquí está el código corregido:

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

Las -gepruebas también son redundantes, ya que estos casos están implicados al llegar a elif/ else, por lo que se han eliminado.

Graeme
fuente
2
Sin embargo, para comprobar contra umbrales, no se desea redondear hacia arriba . 49.6 aún debería estar bien si el umbral de advertencia es 50. Entonces result=$(( 100 * $used / $total ))debería estar bien.
Stéphane Chazelas
0

Así que no sé cómo usarlo awkmuy bien. Pero sí sé que lo que está sucediendo en el script que vinculó es una gran tontería y que algo como lo siguiente debería funcionar. Lo siento, no puedo escribir esto perfectamente bien, pero como ya estás llamando awk, al parecer dos veces, deberías estar usando algo como esto.

_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
fuente