Erro de script bash: expressão inteira esperada

13

Estou com um problema bastante estranho, estou executando um script (Bash) em vários servidores e ele parou de funcionar em um dos servidores (funciona perfeitamente em todos os outros servidores).

Aqui está a parte problemática do script: (eu não o escrevi, todos os créditos vão para "Rich") ( http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios- e-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

Mensagem de erro completa:

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

Se precisar de mais informações, entre em contato e tentarei fornecê-las o mais rápido possível.

Aprecie todas as entradas :)

Adalsteinn
fonte

Respostas:

5

No link que você forneceu, vejo a linha abaixo.

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

De acordo com o comentário de @ Graeme, altere a linha acima para abaixo.

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

Agora, depois de adicionar a linha acima, temos que alterar a saída de resultpara inteiro como abaixo.

result1=${result/.*}

Eu acho que em uma das máquinas onde ocorre o erro, essa saída não é um número inteiro. Basta converter a saída do resultado em número inteiro para que você possa lidar com esses casos. Adicione a linha abaixo depois de calcular o result.

result1=${result/.*}

E em vez de resultalterar os nomes das variáveis ​​como result1dentro dos ifloops, o erro não ocorrerá.

Eu suspeito, os cut -c -2atributos para o erro principalmente porque ele está cortando apenas os 2 primeiros caracteres. E se o resultado tiver apenas um caractere? Suponha que, se o resultado for 1.23456, o corte acima resultará no 1.valor pelo resultqual obviamente é a causa do integer expectederro.

O motivo pelo qual está funcionando bem nos servidores restantes é porque não encontrou um caso em que a resultvariável tenha apenas um dígito. É muito provável que também falhe nos servidores restantes se o resultado for uma variável de um dígito (algo como eu mencionei no exemplo acima).

Ramesh
fonte
${result%%.*}seria a expansão correta para remover o ponto decimal aqui. Mas observe que cut -c -2isso também causará problemas com números de 100 ou mais; portanto, é mais seguro descartá-lo completamente.
Graeme
@ Graeme, eu senti falta disso. Eu deveria ter feito as alterações nessa linha :)
Ramesh
6

Pela aparência, sua resultvariável possui um .após o número que faz o bash não o reconhecer como tal. Você pode reproduzir o erro simplesmente fazendo:

[ 7. -gt 1 ]

Se você adicionar mais do script à sua pergunta, | eu posso sugerir de onde isso pode estar vindo.

Atualizar

Olhando para o script completo, eu apenas substituiria a linha:

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

Com:

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

Como usede totalsão inteiros e basharitméticos inteiros, observe que o deslocamento da multiplicação é 100 para o início. Ou, se você deseja garantir o arredondamento correto ('divisão inteira' na computação sempre efetivamente arredonda para baixo):

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

Isso garantirá que não haja pontos à direita result. A abordagem utilizada cutnão é uma ideia muito boa, pois é válida apenas para resultados no intervalo de 10 a 99. Ele falhará resultentre 0 e 9 (como no seu caso) e também números acima de 99.

Atualização 2

No comentário de @ Stephane abaixo , é melhor arredondar para baixo ao comparar com os limites. Considerando isso, há outro pequeno erro com o trecho na pergunta - observe a inconsistência entre as comparações usadas para warn_leveloe o critical_level. As comparações para warn_levelestão corretas, mas critical_levelusam -le(menor ou igual) em vez de -lt(apenas menor). Considere quando resulté um pouco maior que critical_level- será arredondado para baixo critical_levele não acionará o aviso crítico, mesmo que deva (e faria se uma -ltcomparação fosse usada).

Talvez não seja um problema muito grande, mas aqui está o código corrigido:

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

Os -getestes também são redundantes, pois esses casos estão implícitos em atingir o elif/ else, por isso foram removidos.

Graeme
fonte
2
No entanto, para verificar contra limites, você não quer arredondar para cima . 49.6 ainda deve estar OK se o limite de aviso for 50. Portanto result=$(( 100 * $used / $total )), tudo bem.
Stéphane Chazelas
0

Então, eu não sei usar awkmuito bem. Mas eu sei que o que está acontecendo no script que você vinculou é muito absurdo e que algo como o seguinte deve funcionar. Sinto muito, mas não posso escrever isso perfeitamente, mas como você já está ligando awk- parece que duas vezes -, você deve usar algo assim.

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