Erro de script bash: expressão inteira esperada

12

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

Aqui está a parte problemática do script: (Eu mesmo não escrevi, todos os créditos vão para "Rich") ( )

    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, avise-me e tentarei fornecê-lo o mais rápido possível.

Aprecie todas as entradas:)

    
por Adalsteinn 03.04.2014 / 19:03

3 respostas

4

A partir do link que você forneceu, vejo a linha abaixo.

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

Conforme 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 do result para o inteiro, conforme abaixo.

result1=${result/.*}

Eu acho que em uma das máquinas onde o erro ocorre, esta saída não é um 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 result , altere os nomes das variáveis como result1 dentro dos if loops e o erro não ocorrerá.

Eu suspeito que os atributos cut -c -2 para o erro, na maioria das vezes, estejam apenas cortando os dois primeiros caracteres. E se o resultado tiver apenas um caractere? Suponha que se o resultado for 1.23456 , o corte acima resultará em 1. como o valor para result , que obviamente é a causa do erro integer expected .

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

    
por 03.04.2014 / 19:13
6

Pelo que parece, sua variável result tem um . após o número que faz o bash não reconhecê-lo como tal. Você pode reproduzir o erro simplesmente fazendo:

[ 7. -gt 1 ]

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

Atualizar

Olhando para o script completo, basta substituir a linha:

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

Com:

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

Como used e total são inteiros e bash faz aritmética inteira, embora note que o deslocamento da multiplicação é 100 para o início. Ou se você quiser 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 finais em result . A abordagem usando cut não é uma boa ideia, pois é válida apenas para resultados no intervalo de 10 a 99. Ele falhará por um result de 0-9 (como no seu caso) e também números acima de 99.

Atualização 2

De @ Comentário do Stephane abaixo , é melhor arredondar para baixo quando comparar com os limites. Considerando isso, há outro pequeno erro com o snippet na questão - observe a inconsistência entre as comparações usadas para o warn_level e o critical_level . As comparações para warn_level estão corretas, mas critical_level usa -le (menor ou igual) em vez de -lt (apenas menor). Considere quando result é um pouco maior que critical_level - ele será arredondado para critical_level e não acionará o aviso crítico, embora deva (e seria, se fosse usada uma comparação -lt ).

Talvez não seja um problema, 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 testes -ge também são redundantes, pois esses casos estão implícitos ao atingir o elif / else , portanto, foram removidos.

    
por 03.04.2014 / 19:12
0

Então eu não sei como usar awk muito bem. Mas eu sei que o que está acontecendo no script que você vinculou é um monte de bobagens e que algo como o seguinte deveria funcionar. Me desculpe, eu não posso escrever isso perfeitamente, mas já que você já está chamando awk - duas vezes parece - você deveria estar usando 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
    
por 07.04.2014 / 15:46

Tags