Кодить будем в терминале Linux — он открывается сочетанием клавиш Ctrl + Alt + T. Если вы хотите научиться работать с Bash, но пока не пользуетесь Linux, то пишите код в одном из онлайн-терминалов — например, Replit.
Переменные в Bash объявляются просто:
message="Hello, World!"
Теперь переменная message хранит значение — текстовое сообщение «Hello, World!». Давайте выведем его — сделать это можно с помощью команды echo:
echo $message # Будет выведено «Hello, World!»
Обратите внимание на отсутствие пробелов. В Bash пробелы являются разделителями. Если пробелы есть, то Bash будет считать их отдельными токенами и выдавать ошибки.
Следующий код приведёт к ошибке:
message = "Hello, World!"
bash: message: command not found
Также обратите внимание на символ $ — в Bash он называется символом расширения (expansion character). Поставленный перед именем переменной, он указывает на то, что нужно использовать именно значение переменной, а не одноимённую строку.
Следующий код выведет сообщение «message»:
message="Hello, World!"
echo message
Чтобы сохранить в переменной введённое пользователем значение, используйте команду read:
read name
# Пользователь вводит что-то — например, «Olga»
echo $name # Будет выведено «Olga»
Если вы хотите добавить сообщение перед пользовательским вводом, добавьте флаг -p и сообщение после команды read:
read -p "Enter your name: " name # Будет выведено «Enter your name: »
# Пользователь вводит что-то — например, «Olga»
echo $name # Будет выведено «Olga»
В Bash есть несколько правил именования переменных:
Ну что же, вот мы и создали нашу первую переменную. Поздравляем! Пока эта переменная содержит всего один тип данных — строковый (string). Но в Bash он далеко не единственный — давайте разберём ещё несколько.
Важная оговорка
В Bash нет строгой системы типов, как в некоторых других языках. Тип данных зависит от содержимого переменной и контекста её использования. Поэтому термин «типы данных» в этой статье используется условно, для облегчения понимания. Простите нам это упрощение.
Строки (strings) — это набор символов, заключённый в кавычки. В Bash можно писать строки в одинарных '…' или двойных "…" кавычках. Например, 'Привет' и "Мир" — это строки.
Числа (numbers) — это целочисленные значения. Bash поддерживает арифметические операции с целыми числами, включая сложение, вычитание, умножение и деление. Арифметические выражения нужно предварять знаком $ и обрамлять двойными круглыми скобками:
a=2 b=3 echo $(($a + $b)) # Будет выведено 5
Также можно использовать команду expr:
echo $(expr $a + $b) # Будет выведено 5
Стандартные библиотеки Bash поддерживают следующие арифметические операции:
Примечание: арифметические операторы в Bash не работают с числами с плавающей точкой.
Массивы (arrays) — тип переменных, который может хранить несколько значений. Элементы массива перечисляются в круглых скобках через пробел:
my_array=(apple banana cherry)
При использовании переменной массива в команде применяются фигурные скобки. Если мы хотим вывести его отдельные элементы, это можно сделать с помощью символа $ и номера индекса в квадратных скобках:
echo ${my_array[0]} # Выведет «apple»
echo ${my_array[1]} # Выведет «banana»
echo ${my_array[2]} # Выведет «cherry»
А если нам нужно получить сразу все элементы массива, вместо индекса в квадратных скобках нужно поставить символ * или @:
echo ${my_array[*]} # Выведет «apple banana cherry»
echo ${my_array[@]} # Выведет «apple banana cherry»
Логические значения (boolean) — нужны для того, чтобы проверить, выполняется ли какое-то условие или нет. Они могут быть либо true (истина), либо false (ложь). Например, в операторах if и while мы пишем условие, и если оно true, то выполняем какое-то действие.
В Bash логические значения представлены целыми числами. Число 0 означает true, а любое другое число означает false. Когда мы выводим логическое значение на экран, то вместо true мы видим 0.
Также в Bash есть операторы сравнения. Например, эти нужны для строк:
А эти — для чисел:
Использовать операторы сравнения можно с помощью команды test. Команда test принимает два значения и оператор сравнения и возвращает 1 или 0 в зависимости от результата:
test "hello" = "hello"
echo $?
# Выведет 0 (true), так как строки одинаковые
test "hello" != "world"
echo $?
# Выведет 0 (true), так как строки различаются
Помимо команды test, операторы сравнения можно использовать квадратных скобках [ ]. Но для этого нам понадобится разобраться, как работать с ветвлениями.
Ветвления if-then-else позволяют проверить условие и выполнить один набор команд, если условие истинно, и другой набор команд, если условие ложно. Это выглядит так:
if [ условие ];
then
# Команды, которые нужно выполнить, если условие истинно
else
# Команды, которые нужно выполнить, если условие ложно
fi
Обратите внимание: открывающую и закрывающую квадратные скобки нужно отделять от операндов пробелами.
А если в паре с основным условием нужно проверить дополнительное, используют конструкцию elif:
if [ условие_1 ];
then
# Команды, которые нужно выполнить, если условие_1 истинно
elif [ условие_2 ];
then
# Команды, которые нужно выполнить, если условие_2 истинно
else
# Команды, которые нужно выполнить, если все условия ложны
fi
Существует и более короткая форма записи условной конструкции — if-then. Её используют, когда нужно проверить только одно условие:
if [ условие ];
then
# Команды, которые нужно выполнить
fi
В этом случае команды будут выполнены, только если условие истинно.
Для наглядности давайте напишем скрипт, который проверяет правильность введённого пароля:
#!/bin/bash
# Задаём значение переменной password
password="14pomTEr"
# Запрашиваем ввод пароля у пользователя и сохраняем полученное значение в переменную user_input
read -p "Enter the password: " user_input
# Сравниваем значение переменной password с введённым пользователем значением user_input
if [ "$password" = "$user_input" ]; then
# Если пароли совпадают, выводим сообщение о том, что пароль введён правильно
echo "Password accepted"
else
# Если пароли не совпадают, выводим сообщение о том, что пароль введён неправильно
echo "Wrong password"
fi
Кроме того, в Bash есть логические операторы & & (логическое И) и || (логическое ИЛИ), которые позволяют комбинировать несколько условий и возвращать соответствующее булево значение.
Например, вот как будет выглядеть наша программа, если мы добавим проверку логина:
#!/bin/bash
username="OlgaBelova94" # Устанавливаем переменную с именем пользователя
password="14pomTEr"
read -p "Enter your username: " user_input_username # Запрашиваем имя пользователя
read -p "Enter the password: " user_input_username # Запрашиваем пароль
echo "Enter the password: "
read user_input_password # Запрашиваем пароль
if [ "$username" == "$user_input_username" ] && [ "$password" == "$user_input_password" ]; then
echo "Password accepted"
else
echo "Wrong username or password" # Уточняем, что именно было неверно
fi
Здесь мы получим значение true и сообщение «Password accepted», только если будут выполнены оба условия.
Как и в большинстве языков программирования, в Bash есть циклы. Они бывают двух видов:
Вот как выглядит сигнатура цикла for:
for переменная цикла in элемент1 элемент2 ... элементN
do
# Команды, которые будут выполняться в цикле
done
Количество итераций (часть между in и do) можно указать простым перечислением элементов:
for fruit in apple banana cherry
do
echo "I like $fruit"
done
# Будет выведено:
# I like apple
# I like banana
# I like cherry
Можно перебрать элементы массива:
my_array=("apple" "banana" "orange")
for fruit in "${my_array[@]}"
do
echo "I like $fruit"
done
# Будет выведено:
# I like apple
# I like banana
# I like cherry
Для явного указания нужного количества итераций используют арифметические выражения:
for ((i=0; i<5; i++))
do
echo "Iteration number $i"
done
# Будет выведено:
# Iteration number 0
# Iteration number 1
# Iteration number 2
# Iteration number 3
# Iteration number 4
А вот так выглядит сигнатура цикла while:
while [ условие ]
do
# Команды, которые будут выполняться в цикле
done
Условие (condition) — это выражение, результат которого является логическим значением true или false. Команды внутри цикла будут выполняться до тех пор, пока condition возвращает true.
Давайте усовершенствуем нашу программу проверки пароля так, чтобы она запрашивала его до тех пор, пока пользователь не введёт верный:
#!/bin/bash
password="14pomTEr"
user_input=""
while [ "$user_input" != "$password" ]
do
read -p "Enter the password: " user_input
echo "Wrong password, login denied"
done
echo "Password accepted, login allowed"
Что здесь происходит. В этом примере цикл while запрашивает пароль у пользователя, а потом проверяет его на совпадение с правильным с помощью оператора ["$user_input" != "$password"]. А дальше происходит следующее:
Функции на языке Bash имеют такой вид:
имя_функции (аргументы) {
# Тело функции
}
Например, вот как выглядит простая функция без аргументов:
say_hello () { # Создаём функцию
echo hello
}
say_hello # Вызываем функцию, будет выведено «hello»
А вот как выглядит функция, которая принимает аргументы:
repeat_text () {
local text=$1
local reps=$2
for (( i=0; i<$reps; i++ )); do
echo "$text"
done
}
repeat_text "hello" 3
Что здесь происходит:
Настало время применить знания на практике — напишем скрипт для автоматической очистки кэша браузера и DNS.
Состоять наш скрипт будет из трёх функций: первая — для очистки кэша браузера, вторая — для очистки кэша DNS, а в третью завернём небольшое меню для выбора нужного действия.
Начинаем, как водится, с шебанга — специальной строки, которая говорит компьютеру, с помощью какой программы нужно запускать скрипт. Так как мы хотим использовать bash, которая лежит в папке /bin, шебанг будет выглядеть так:
#!/bin/bash
Теперь напишем функцию, которая будет очищать браузерный кэш. В комментариях — разбор синтаксиса.
clear_browser_cache() {
# Проверяем, какой браузер установлен на компьютере
if command -v google-chrome >/dev/null 2>&1; then
# Если установлен Google Chrome, очищаем кэш браузера
google-chrome --user-data-dir=$(mktemp -d) --disable-extensions --disable-plugins --disable-geolocation --no-default-browser-check --no-first-run --noerrdialogs --disable-session-crashed-bubble --disable-infobars --disk-cache-size=0 --media-cache-size=0
# Далее проверяем, установлен ли Firefox
elif command -v firefox >/dev/null 2>&1; then
# Если установлен Firefox, очищаем кэш браузера
firefox --new-instance --safe-mode
# Если браузер не установлен, выводим сообщение об ошибке
else
echo "Error: no supported browser found"
fi
}
Далее напишем функцию для очистки кэша DNS.
clear_dns_cache() {
# Проверяем, какая операционная система установлена на компьютере
# Если установлена Linux, очищаем кэш DNS
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
sudo systemd-resolve --flush-caches
# Если установлена macOS, очищаем кэш DNS
elif [[ "$OSTYPE" == "darwin"* ]]; then
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
# Если операционная система не поддерживается, выводим сообщение об ошибке
else
echo "Error: unsupported operating system"
fi
}
Ну а теперь дело за малым. Напишем небольшое меню, чтобы пользователь мог выбрать, кэш браузера или кэш DNS нужно очистить.
# Сначала выведем варианты
clear_cache() {
echo "Select cache to clear:"
echo "1. Browser cache"
echo "2. DNS cache"
# Запросим у пользователя номер выбранного пункта меню
read -p "Enter your choice: " choice
# В зависимости от выбранного пункта меню вызываем соответствующую функцию для очистки кэша
if [ "$choice" -eq 1 ]; then
clear_browser_cache
elif [ "$choice" -eq 2 ]; then
clear_dns_cache
else
echo "Invalid choice"
fi
}
Вуаля! Наш скрипт готов. Чтобы его запустить, нам нужно лишь вызвать функцию clear_cache:
clear_cache
В теории можно сделать скрипт и ещё лучше — например, добавить больше браузеров, реализовать проверку прав администратора и другие фишки. Но на сегодня, пожалуй, достаточно.
Задание 1.
Разработать bash скрипт для установки node_exporter prometheus, он должен автоматически запускаться при старте компьютера и работать на порте 3100.
Скачать нужную версию node_exporter для debian можно по ссылке: скрипт
Скрипт должен: