Назад | Перейти на главную страницу

Оценка Bash сбивает с толку

Я пытаюсь заставить скрипт что-то делать, когда одно число больше другого, в данном случае, когда средняя загрузка системы превышает определенное значение.

Все это работает помимо критериев оценки.

Пока я создаю еще один сервер для некоторых сайтов, я пытаюсь поддерживать apache в рабочем состоянии, причины не важны, но этот сценарий был протестирован и протестирован в системе, в которой средняя загрузка ниже 15 и сценарий распечатывает:

«check составляет 4.68, а max - 15.00» НЕСМОТРЯ на условие if, говорящее ему не печатать вообще ничего, если значение check не превышает max load, а это не так.

Я не гуру bash, у меня есть борода, но нет сандалий, и я пробовал использовать различные стили скобок и цитирования, но я не могу понять, почему этот скрипт вообще что-то печатает, когда $ check меньше $ max_load .

Это Debian 6, GNU bash, версия 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

В системе с загрузкой около 4 этот скрипт выводит:

"check is 4.68 and max is 15.00"

Кто-нибудь знает почему?

Любая помощь и предложения по поводу хороших сандалий для начинающих будут очень признательны!

Это не сработает. В > оператор внутри [[ сравнивает Порядок сортировки, а не значение. Так....

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

... потому что 4 сортируются после 1, что означает [[ 4.68 > 15.00 ]] правда. И ты не можешь использовать -gt, потому что для этого нужны целые числа.

Если вас интересуют только целочисленные пороги, это легко исправить - усечь на ., используйте -gt, и вот так. В противном случае используйте bc - видеть https://unix.stackexchange.com/questions/24721/how-to-compare-to-floating-point-number-in-a-shell-script

Спасибо всем, последнее решение, которое хорошо работает в моей системе Debian, заключалось в том, что сначала преобразовало его в int, а затем с помощью -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

Согласно документам, <, и > площадь лексическая сортировка. Я не уверен, но я почти уверен, что это то же самое, что вы получили бы, если бы использовали что-то вроде sort. С сортировкой, 15.00 раньше 4.68 потому что он в основном сортирует символы по символам. Так 1 раньше 4 в большинстве регионов.

Поскольку ваше примерное значение 4.68 будет после 15.0 лексически отсортированные, > возвращает истину.

Вы почти наверняка хотели, чтобы ваши строки рассматривались как числа, поэтому вы должны использовать -gt, или -lt, но они ограничены целыми числами.

Ссылка: http://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html

строка1 <строка2 Истинно, если строка1 лексикографически сортируется перед строкой2.

строка1> строка2 Истинно, если строка1 лексикографически сортируется после строки2.

Основная проблема в том, что Bash поддерживает только целое число арифметика. Вы можете обойти это, используя инструмент, который поддерживает числа с плавающей запятой, что удобно в Awk.

(Я бы также исключил бесполезный cat и обратите внимание, что sed | awk аналогично бесполезно.)

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

Если вы хотите использовать это в условной оболочке, заставьте Awk возвращать нулевой код выхода в случае успеха и ненулевой в случае ошибки:

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