Ошибка разбора значения памяти в скрипте bash: ожидается целочисленное выражение

Вопрос или проблема

У меня есть следующий скрипт для проверки свободной памяти:

#!/bin/bash
THRESHOLD="500"
FREE_MEM=$(free -mh | awk '/^Mem:/{print $4}')

if [ "$FREE_MEM" -lt "$THRESHOLD" ]; then
        echo "недостаточно памяти. Доступная память составляет ${FREE_MEM} MB"
fi

Однако я получаю эту ошибку:

./memory_monitor.sh: line 6: [: 135Mi: ожидается целочисленное выражение

На системе Ubuntu 24.04.1 LTS с 32 ГБ памяти команда free, запущенная из скрипта, дает следующий результат:

$ free -mh | awk '/^Mem:/{print $4}'
25Gi

Обратите внимание, что использование опции h (или --human) приводит к тому, что вывод отображается в единицах гигабайт. Из man free:

       -h, --human
              Показать все выходные поля, автоматически масштабируемые до самого короткого
              трехзначного значения и отображать единицы вывода.  Используются следующие единицы.

                B = байты
                Ki = кибибайты
                Mi = мебибайты
                Gi = гибибайты
                Ti = тебибайты
                Pi = пебибайты

Суффикс Gi приведет к ошибке ожидается целочисленное выражение.

Поэтому удалите опцию h, чтобы получить значение в мебибайтах без суффикса. То есть:

#!/bin/bash
THRESHOLD="500"
FREE_MEM=$(free -m | awk '/^Mem:/{print $4}')

if [ "$FREE_MEM" -lt "$THRESHOLD" ]; then
        echo "недостаточно памяти. Доступная память составляет ${FREE_MEM} MiB"
fi

Или, если вы хотите мегабайты (степень 1000), а не мебибайты (степень 1024), как подразумевает ваш MB, используйте free --mega вместо free -m.

Как указывает ответ “Chester Gillon”, вам нужно использовать -m без h.

Вы также можете использовать $7 для вывода, потому что free — это не доступная память.

#!/bin/bash
THRESHOLD=500
FREE_MEM=$(free -m | awk '/^Mem:/{print $7}')

if [ "$FREE_MEM" -lt "$THRESHOLD" ]; then
    echo "Недостаточно памяти. Доступная память составляет ${FREE_MEM} MiB"
else
    echo "Достаточно памяти. Доступная память составляет ${FREE_MEM} MiB"
fi

В выводе free,

Свободная память — это количество памяти, которое в настоящее время не используется ни для чего. Эта цифра должна быть небольшой, потому что неиспользуемая память просто теряется.

Доступная память — это количество памяти, которое доступно для выделения новому процессу или существующим процессам.

Что такое доступная память при использовании команды free?

Что означает поле “доступно” в команде “free -m”

Что такое доступная и свободная память в ответ на команду free в Linux?

Ошибка заключается в этой строке:

FREE_MEM=$(free -mh | awk '/^Mem:/{print $4}')

потому что вы используете флаг -h, который показывает значения в удобочитаемом формате и добавляет букву к числовому значению, например, 143M вместо 143.

Затем следующая строка вызывает ошибку:

if [ "$FREE_MEM" -lt "$THRESHOLD" ]; then

потому что она ожидает числовое значение в качестве первого аргумента.

Таким образом, скрипт нужно исправить следующим образом:

FREE_MEM=$(free -m | awk '/^Mem:/{print $4}')

Ответ или решение

Ошибка «Error parsing memory value in bash script: expected integer expression», с которой вы столкнулись в вашем bash-скрипте, является следствием того, что вы используете опцию -h (читаемая человеком) при выполнении команды free. Эта опция приводит к тому, что вывод команды содержит суффиксы для обозначения единиц измерения, таких как Mi, Gi и др. Это усложняет дальнейшую работу со значениями, поскольку операторы сравнения в bash ожидают числовых значений без суффиксов.

Анализ проблемы

Ваша строка, вызывающая ошибку, выглядит следующим образом:

FREE_MEM=$(free -mh | awk '/^Mem:/{print $4}')

С помощью этой команды вы пытаетесь получить количество свободной памяти, но опция -h делает вывод в формате, который включает единицы измерения. Например, вместо чистого числа вы получаете выходные данные вроде 25Gi, что и приводит к ошибке «integer expression expected» (ожидается целочисленное выражение) при попытке выполнить и сравнить значение.

Решения проблемы

Чтобы исправить эту ошибку, вам следует:

  1. Удалить опцию -h, чтобы получить значение без суффиксов. Это можно сделать следующим образом:
FREE_MEM=$(free -m | awk '/^Mem:/{print $4}')

Таким образом, при использовании -m вы будете получать значение свободной памяти в мебибайтах (MiB) без каких-либо дополнительных символов.

  1. Сравнение значений: После изменения данной строки, ваш код будет выглядеть примерно так:
#!/bin/bash
THRESHOLD=500
FREE_MEM=$(free -m | awk '/^Mem:/{print $4}')

if [ "$FREE_MEM" -lt "$THRESHOLD" ]; then
    echo "Недостаточно памяти. Доступная память составляет ${FREE_MEM} MiB"
else
    echo "Достаточно памяти. Доступная память составляет ${FREE_MEM} MiB"
fi

Альтернативный подход

Если вам необходимо использовать значения в мегабайтах (по 1000 байт), вы также можете использовать команду free с флагом --mega:

FREE_MEM=$(free --mega | awk '/^Mem:/{print $4}')

Тем не менее, по умолчанию free -m предоставляет удобные значения, учитывающие порядок 1024 (в мебибайтах).

Объяснение разницы между «свободной» и «доступной» памятью

Следует обратить внимание на различие между терминами «свободная» и «доступная» память. Свободная память — это количество памяти, которое в данный момент не используется. В то время как доступная память — это память, которая может быть перераспределена под новые процессы, и она быстрее доступна для использования. Ваша исходная строка могла возвращать неправильное значение (например, $4 для «свободной памяти»), когда значение по $7 представляло «доступную память» в выводе команды free.

Вы можете изменить выбор столбца на awk, чтобы получить значение доступной памяти, следующим образом:

FREE_MEM=$(free -m | awk '/^Mem:/{print $7}')

Заключение

С помощью простых изменений в вашем скрипте вы сможете избежать ошибок при работе с памятью в bash. Убедитесь, что вывод, с которым вы работаете, соответствует ожидаемому формату, а также уточните, какую именно память вы хотите контролировать — свободную или доступную. Эти изменения помогут вам создать более надежный скрипт для мониторинга памяти в системах Linux.

Оцените материал
Добавить комментарий

Капча загружается...