Выбор команд для выполнения в bash-скрипте можно контролировать с помощью особых блоков кода — управляющих конструкций. К ним относятся условные операторы, циклы и группирующие команды.
В первой части материала об условных операторах расскажем, как работать с условными конструкциями для проверки истинности [ … ]
и [[ … ]]
, во второй — об условных операторах if
и case
, а также о логических операторах &&
(логическое И) и ||
(логическое ИЛИ).
Одинарные [ … ] и двойные [[ … ]] квадратные скобки
Одинарные [ … ]
и двойные [[ … ]]
квадратные скобки — самостоятельные условные конструкции, которые проверяют истинность помещённого в них выражения. Также в них часто помещают тело условия после оператора if
. От выбора конструкции зависит форма записи условия — оболочка интерпретирует выражения в одинарных квадратных скобках иначе, чем в двойных.
Конструкция [ … ]
— встроенная команда (builtin) оболочки bash. Это форма записи команды test
, которая проверяет выполнение условия.
В этой конструкции для аргументов действуют подстановка значений переменных, разделение на слова и поиск по шаблонам (globbing — об этом подробно рассказано в статье Часть 2. Bash-скрипты. Переменные, комментарии, пользовательский ввод). Чтобы спецсимволы внутри одинарных квадратных скобок интерпретировались как операторы (например, =, >, &&, |, ., *
и так далее), их нужно экранировать при помощи обратного слэша \
или двойных кавычек ""
. Внутри конструкции [ … ]
нельзя работать с регулярными выражениями и сравнивать строки между собой.
Одинарные скобки используются не только в bash, но и в остальных POSIX-системах.
Пример использования:
file="file name"
[ -f "$file" ] && echo "$file — обычный файл"
Так как значение переменной file
содержит пробел, внутри конструкции [ … ]
имя переменной нужно заключить в кавычки, иначе оболочка интерпретирует значение переменной как два отдельных слова, и возникнет ошибка — указанный файл не будет найден.
Конструкция [[ … ]] — ключевое слово (keyword) оболочки bash. Помещаемые в неё аргументы интерпретируются особым образом — специальные символы не требуется экранировать, а разделение на слова и поиск по шаблонам не работают. Внутри двойных одинарных скобок можно работать с регулярными выражениями и сравнивать строки между собой.
Двойные квадратные скобки менее универсальны, чем одинарные — они предусмотрены в оболочках ksh, zsh и bash, но отсутствуют в sh, ash и dash.
Пример использования:
file="file name"
[[ -f $file ]] && echo "$file — обычный файл"
Так как значения переменных внутри конструкции [[ … ]]
оболочка не делит на слова, имена переменных в ней не нужно заключать в кавычки.
Выбор оператора сравнения зависит от договорённости в сообществе или предпочтений разработчика. Например, компания Google в своём стиле кода рекомендует использовать в shell-скриптах конструкцию [[ … ]]
вместо [ … ]
, test
и /usr/bin/[
. По мнению авторов конвенции, это самый надёжный вариант записи: он позволяет избежать ошибок интерпретации, так как не требуется экранирование спецсимволов или иные способы записи операторов (например, -a
вместо &&
). Кроме того, внутри двойных квадратных скобок можно сравнивать последовательности символов и работать с регулярными выражениями, а конструкция [ … ]
не поддерживает эти возможности.
Проверка файлов
В скриптах с оператором if
часто проверяют тип и разрешения файлов. Для проверки используют оператор [ ... ]
(команды test
) и следующие его опции:
| возвращает true (устанавливает, что условие выполнено), если указанный файл существует и является обычным файлом (а не, например, каталогом или символической ссылкой) |
| возвращает true, если указанный файл существует и является каталогом |
| возвращает true, если указанный файл содержит данные (то есть размер файла больше нуля) |
| возвращает true, если указанный файл доступен для чтения |
| возвращает true, если указанный файл доступен для записи |
| возвращает true, если указанный файл является исполняемым файлом |
Пример проверки исполняемости файла:
#!/bin/bash
if [ -x script.sh ]; then
echo 'script.sh можно запустить на исполнение'
else
echo 'script.sh нельзя запустить на исполнение'
fi
Этот скрипт проверяет, может ли действующий пользователь запустить файл на исполнение — установлен ли для него бит исполнения x
. Если этот бит присутствует, скрипт возвращает значение true, и выводится сообщение: script.sh
можно запустить на исполнение
. Если отсутствует — сообщение: script.sh
нельзя запустить на исполнение
.
Сравнение строк
Две строки равны, если они содержат одну и ту же последовательность символов. В скриптах с оператором if
часто проверяют строки на равенство. Для этого используют оператор [ ... ]
со следующими операторами:
| Возвращает true, если операнды (сущности, участвующие в операции) равны. Особенности использования операторов = и == с операторами [ ... ] и [[ ... ]] С одинарными квадратными скобками:
С двойными квадратными скобками:
|
string1 != string2 | Возвращает true, если операнды не равны. |
string1 > string2 | Возвращает true, если правый операнд располагается первым при сортировке в алфавитном порядке:
|
string1 < string2 | Возвращает true, если левый операнд располагается первым при сортировке в алфавитном порядке.
|
-z string | Возвращает true, если длина строки равна нулю. |
-n string | Возвращает true, если длина строки не равна нулю. |
-v string | Возвращает true, если назначена переменная с таким именем. |
"string" =~ regular_expression | Возвращает true, если строка соответствует регулярному выражению:
|
Следующий скрипт проверяет, запущен ли определённый сервис, которым управляет systemctl
— подсистема инициализации и управления службами во многих дистрибутивах Linux:
#!/bin/bash
echo "Введите название сервиса: "
read service_name
status=$(systemctl is-active $service_name)
if [ "$status" = "active" ]; then
echo "Сервис $service_name запущен."
else
echo "Сервис $service_name не запущен."
fi
- Пользователю предлагают ввести имя одного из системных сервисов Linux.
- Введённое значение подставляется в команду
systemctl
, которая проверяет состояние сервиса с указанным названием. Результат выполнения командыsystemctl
сохраняется в переменнуюstatus
. - Если значение переменной —
active
, отображается сообщение о том, что сервис запущен. - Во всех прочих сценариях (включая случай, когда сервис не установлен в системе) отображается сообщение о том, что сервис не запущен.
Сравнение чисел
Для сравнения чисел используют оператор [ ... ]
и следующие операторы:
-eq | равно (equal) |
-ne | не равно (not equal) |
-gt | больше (greater than) |
-lt | меньше (less than) |
-ge | больше или равно (greater or equal) |
-le | меньше или равно (less or equal) |
Эти операторы работают только с целыми числами.
В следующем скрипте используется утилита sensors
для измерения температуры ЦП. Она входит в пакет lm-sensors
, который отслеживает значения параметров аппаратного обеспечения компьютера.
Команда установки пакета lm-sensors
для операционных систем семейств Ubuntu и Debian:
sudo apt install lm-sensors
Для систем CentOS и RHEL:
sudo yum install lm-sensors
Скрипт проверяет текущую температуру одного из ядер процессора — Core 0:
#!/bin/bash
current_temp=$(sensors | grep "Core 0" | awk '{print $3}' | sed 's/+//; s/°C//' | head -n 1)
current_temp_int=$(bc <<< "${current_temp}/1")
threshold=80
if [ "$current_temp_int" -gt "$threshold" ]; then
echo "Внимание: высокая температура! Текущая температура: ${current_temp}°C."
else
echo "Температура нормальная. Текущая температура: ${current_temp}°C."
fi
Скрипт выполняет следующие действия:
- В переменную
current_temp
записывается вывод конвейера из следующих команд:- Вывод команды
sensors
передаётся командеgrep
для поиска строки (или строк) с фрагментомCore 0
. - Вывод
grep
передаётся команде для обработки текстаawk
, которая находит третье поле полученной строки и выводит его. - Вывод
awk
передаётся командеsed
, которая удаляет символ+
перед значением температуры и°C
после него. - Так как процессоров с ядром
Core 0
может быть несколько, утилитаhead
оставляет только первую из обработанных строк с фрагментомCore 0
.
- Вывод команды
- Так как операторы сравнения чисел работают только с целыми числами, а программа
sensors
выводит значения температуры с плавающей точкой, значение переменнойcurrent_temp
преобразуется в целое: делится на единицу и передаётся в виде here-строки программе-калькуляторуbc
, а затем в преобразованном виде записывается в переменнуюcurrent_temp_in
t. - Переменной
threshold
присваивается значение 80. - Команда
echo
выводит результат сравнения значений переменныхcurrent_temp_int
иthreshold
.
Таким образом скрипт проверяет: значение переменной current_temp_int
больше значения переменной threshold
?
Если да, то выводится сообщение:
Внимание: повышенная температура! Текущая температура — <значение переменной $current_temp>.
Если нет, то выводится сообщение:
Температура нормальная. Текущая температура — <значение переменной $current_temp>.
Мы рассмотрели условные конструкции в языке bash: узнали, как работать с одинарными [ … ]
и двойными [[ … ]]
квадратными скобками, которые в bash-скриптах позволяют проверять выполнение условий для разных типов данных.
Во второй части статьи расскажем, как работать с операторами if
и case
, а также с логическими операторами &&
и ||
.