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 ksh93
o zsh
1 ) no puede hacer aritmética de punto flotante. awk
Sin 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 zsh
embargo, 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 loadavg
es 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
bash
no 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