avaliação de Bash desconcertante

3

Estou tentando fazer com que um script faça alguma coisa quando um número é maior que o outro, neste caso, quando a média de carregamento do sistema excede um valor definido.

Tudo isso está trabalhando fora dos critérios de avaliação.

Embora eu construa outro servidor para alguns sites, estou tentando manter o apache alinhado, os motivos não são importantes, mas esse script foi testado e testado em um sistema em que a média de carga está abaixo de 15 e o script é impresso :

"a verificação é 4.68 e o máximo é 15.00" APESAR da condição if dizendo para não imprimir nada se o valor da verificação não for maior que a carga máxima, o que não é.

Eu não sou nenhum guru, eu tenho barba, mas não tenho sandálias e eu tentei uma variedade de estilos diferentes de parênteses e citações, mas não consigo entender por que esse script imprime qualquer coisa quando $ check é menor de $ max_load.

Isto está no Debian 6, GNU bash, versão 4.1.5 (1) -release- (x86_64-pc-linux-gnu)

#!/bin/bash
check='cat /proc/loadavg | sed 's/./ /' | awk '{print $2}''
max_load='15.00';
high_load_log='/var/log/apache2/apache_high_load_restart.log';
apache_init='/etc/init.d/apache2';

if [[ $check > $max_load ]]; then
   echo " check is $check and max is $max_load";
   #$apache_init stop
   sleep 5;
   #$apache_init restart
   echo "$(date) : Apache Restart due to load of | $check |" >> $high_load_log;
fi

Em um sistema com uma carga de aproximadamente 4, esse script gera:

"check is 4.68 and max is 15.00"

Alguém sabe por quê?

Qualquer ajuda e sugestão para boas sandálias iniciais serão muito apreciadas!

    
por DrBobblechops 05.03.2015 / 00:06

4 respostas

3

Isso não vai funcionar. O operador > dentro de [[ compara a ordem de classificação , não o valor. Então ....

$ echo -e '4.68\n15.00'|sort
15.00
4.68

... porque 4 classifica após 1, o que significa que [[ 4.68 > 15.00 ]] é verdadeiro. E você não pode usar -gt , porque isso requer números inteiros.

Se você se importa apenas com limites inteiros, essa é a solução mais fácil - trunque em . , use -gt e lá vai você. Caso contrário, use bc - consulte link

    
por 05.03.2015 / 00:27
0

De acordo com os documentos, o < e > são um tipo léxico . Não tenho certeza, mas tenho certeza que isso é o mesmo que você obteria se usasse algo como sort . Com a classificação, 15.00 é antes de 4.68 , porque basicamente ordena caractere por caractere. Portanto, 1 é antes de 4 na maioria das localidades.

Como seu valor de exemplo 4.68 seria depois de 15.0 classificado lexicalmente, o > retornará verdadeiro.

Você quase certamente queria que suas strings fossem tratadas como números, então você usaria -gt ou -lt , mas elas são limitadas a números inteiros.

Ref: link

string1 < string2 True if string1 sorts before string2 lexicographically.

string1 > string2 True if string1 sorts after string2 lexicographically.

    
por 05.03.2015 / 00:26
0

Obrigado a todos, a solução final que funciona bem no meu sistema Debian foi isto, essencialmente convertendo-o para um int primeiro, usando então -gt.

#!/bin/bash
check='cat /proc/loadavg | sed 's/ / /' | awk '{print $1}''
checkint=${check/\.*}
max_load='20';
high_load_log='/var/log/apache2/apache_high_load_restart.log';
apache_init='/etc/init.d/apache2';

if [ $checkint -gt $max_load ]; then
        echo " check is $checkint and max is $max_load";
        $apache_init stop
        sleep 5;
        $apache_init restart
        echo "$(date) : Apache Restart due to excessive load | $check |" >> $high_load_log;
else
        echo "check is $check resolving down to $checkint and max is $max_load - No Action Taken";
fi
    
por 05.03.2015 / 11:51
0

O problema fundamental é que o Bash suporta apenas a aritmética inteiro . Você pode contornar isso usando uma ferramenta que suporta ponto flutuante, o que convenientemente faz o Awk.

(Eu também fatoraria o % inútil cat e observe que sed | awk é similarmente inútil. )

awk -v max="$max_load" '$1 > max {
    print "check is " $1 " and max is " max }' /proc/loadavg

Se você quiser usar isso em uma condicional de shell, faça com que o Awk retorne um código de saída zero com sucesso, diferente de zero na falha:

if ! check=$(awk -v max="$max_load" '($1 > max) {
       print $1; exit 1 }' /proc/loadavg); then
   echo " check is $check and max is $max_load";
   $apache_init stop
   sleep 5;
   $apache_init restart
   date +"%c : Apache Restart due to load of | $check |" >> $high_load_log;
fi
    
por 06.03.2015 / 13:35