Error: se esperaba una expresión entera

Error: se esperaba una expresión entera

He escrito un script para determinar el promedio de carga en el servidor de la siguiente manera:

#!/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

Cuando se ejecuta el script, muestra el siguiente error:

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

Respuesta1

bash(al contrario de ksh93o zsh1 ) no puede hacer aritmética de punto flotante. awkSin embargo, puedes hacerlo, por lo que puedes hacer todo en formato awk.

Además, no es necesario utilizarlo top(y esperar 1 segundo) para obtener la carga. La forma canónica de obtener la carga es desde 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 Sin zshembargo, debes usar la sintaxis (( loadavg > 2 ))en lugar de [ "$loadavg" -gt 2 ]la sintaxis para comparar números no enteros.

Respuesta2

top -b -n1 | grep -i load | awk -F, '{print$4}'| awk -F: '{print $2}'no devuelve nada, de ahí tus errores.

Respuesta3

Su loadavges nulo, provoca errores de sintaxis por [:

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

Debes cambiarlo a:

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

Sin embargo, deberías utilizar una prueba más nueva en tu script, ya que puede solucionar este problema:

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

Con mayores [:

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

Actualizado

bashno puede manejar números de coma flotante, por lo que su comparación (incluso con una nueva prueba [[..]]) mostrará errores.

Puede utilizar otras herramientas para realizar esta tarea, como bc, awk...

Ejemplo:

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

Respuesta4

En primer lugar, ejecutar la parte superior es más costoso que simplemente aprovechar el "tiempo de actividad".

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

En segundo lugar, como mencionó @Stéphane Chazelas, a bash no le gusta la aritmética de punto flotante.

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

Afortunadamente, la expansión de bash puede encargarse de eso. Dehombre golpe:

   ${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.

Por lo tanto, resulta bastante fácil eliminar las partes decimales con "%.*".

$ 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

información relacionada