Помилка сценарію Bash: очікується ціле вираження


13

У мене досить дивна проблема, я запускаю скрипт (Bash) на декількох серверах, і він перестав працювати на одному з серверів (прекрасно працює на всіх інших серверах).

Ось проблемна частина сценарію: (я не писав його сам, усі кредити переходять до "Річ") ( http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios- і-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

Повне повідомлення про помилку:

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

Якщо вам потрібна додаткова інформація, дайте мені знати, і я спробую її надати якомога швидше.

Вдячні за всі матеріали :)

Відповіді:


5

З наданого вами посилання я бачу рядок нижче.

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

Відповідно до коментаря @ Graeme, змініть вищевказаний рядок на нижній.

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

Тепер, додавши вищевказаний рядок, ми повинні змінити вихід resultна ціле число, як показано нижче.

result1=${result/.*}

Я думаю, що в одній із машин, де виникає помилка, цей вихід не є цілим числом. Просто перетворіть результат результату в ціле число, щоб ви могли обробляти такі випадки. Додайте рядок нижче після обчислення result.

result1=${result/.*}

І замість того, щоб resultзмінювати імена змінних, як result1всередині ifциклів, і помилка не відбудеться.

Я підозрюю, що cut -c -2атрибути до помилки здебільшого, оскільки вона вирізає лише перші два символи. Що робити, якщо результат має лише одного персонажа? Припустимо, якщо результат є 1.23456, вищевказаний розріз призведе 1.до значення, для resultякого, очевидно, є причиною integer expectedпомилки.

Причина, по якій він працює добре на решті серверах, полягає в тому, що він не стикався з випадком, коли resultзмінна має лише одну цифру. Велика ймовірність виходу з ладу і на інших серверах, якщо результатом є одноцифрова змінна (щось подібне я вже згадував у вищенаведеному прикладі).


${result%%.*}було б правильним розширенням для видалення десяткової крапки тут. Але зауважте, що cut -c -2заповіт також спричинить проблеми з цифрами 100 і більше, тому безпечніше його повністю відкинути.
Graeme

@Graeme, я це пропустив. Я повинен був внести зміни в цьому рядку :)
Рамеш,

6

За зовнішнім виглядом речей, ваша resultзмінна має .в ній після числа, що робить bash, не визнає її такою. Ви можете відтворити помилку, просто виконавши:

[ 7. -gt 1 ]

Якщо ви додасте більше сценарію до свого питання, | я можу підказати, звідки це може бути.

Оновлення

Переглядаючи повний сценарій, я би просто замінив рядок:

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

З:

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

Оскільки usedі totalє цілими числами, так і bashчисельною арифметикою, хоча зауважте, що зсув множення буде 100 на початок. Або якщо ви хочете забезпечити правильне округлення ("ціле ділення" в обчислювальних системах завжди ефективно округляється):

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

Це забезпечить відсутність крайових крапок result. Підхід із використанням cutне є дуже хорошою ідеєю, оскільки він справедливий лише для результатів у діапазоні 10-99. Він не матиме значення result0-9 (як у вашому випадку), а також цифри вище 99.

Оновлення 2

З коментаря @ Стефана нижче , вам краще округлити, порівнюючи з пороговими показниками. Враховуючи це, є ще одна невелика помилка з фрагментом у питанні - зауважте невідповідність між порівняннями, які використовуються для warn_levelта critical_level. Порівняння warn_levelє правильними, але critical_levelвикористовує -le(менші або рівні) замість -lt(лише менші). Поміркуйте, коли resultвона трохи більша за critical_level- вона буде округлена до critical_levelта не викликає критичного попередження, навіть якщо воно повинно (і було б, якби -ltбуло використано порівняння).

Можливо, проблеми не так багато, але ось виправлений код:

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

Ці -geтести також зайвим , оскільки ці випадки є в виду при досягненні elif/ else, тому були видалені.


2
Однак, щоб перевірити наявність порогових значень, не хочеться округляти їх . 49.6 має бути все в порядку, якщо пороговий поріг становить 50. Тож result=$(( 100 * $used / $total ))має бути просто добре.
Стефан Шазелас

0

Тож я взагалі не знаю як правильно користуватися awk. Але я знаю, що те, що відбувається в сценарії, який ви зв'язали, - це багато дурниць і що щось подібне повинно працювати. Вибачте, я не можу це виписати ідеально добре, але оскільки ви вже дзвонили awk- двічі, здається, - вам слід використовувати щось подібне.

_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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.