Шпаргалка по Bash скриптам
- Основы bash
- Hello world
- Комментарии
- Переменные
- Пользовательский ввод
- Передача аргументов
- Условия if else
- Операторы условий
- Операторы сравнения для чисел
- Операторы сравнения для строк
- Операторы для проверки файлов
- Логические операторы
- Арифметические операторы
- Конструкция switch case
- Массивы
- Цикл while
- Цикл until
- Цикл for
- Цикл select
- Break и continue в циклах
- Функции
- Локальные переменные
- Ключевое слово readonly
- Обработка сигналов
Основы bash
Скрипты Bash имеют расширение .sh
:
Хорошей практикой считается указывать путь до вашего терминала вначале каждого скрипта:
Этот прием называется shebang, подробнее можно почитать тут
Список доступных терминалов в вашей системе можно посмотреть с помощью этой команды:
Hello world
Запуск скрипта:
Скрипт можно сделать исполняемым файлом и запускать без команды bash
:
Комментарии
Однострочные комментарии:
Мультистрочные комментарии:
Переменные
Имя переменной не должно начинаться с цифры
Пользовательский ввод
Команда read
читает пользовательский ввод и записывает его в указанную переменную:
Если переменная не указана, то команда
read
по умолчанию сохранит все данные в переменнуюREPLY
Можно записывать несколько переменных. Для этого, при вводе из терминала, значения необходимо разделять пробелом:
Флаг -a
позволяет создать массив в который будут записываться строки пользовательского ввода разделенные пробелом:
Флаг -p
позволяет не переносить пользовательский ввод на следующую строку.
Флаг -s
позволяет скрыть вводимые символы (как это происходит при вводе пароля).
Передача аргументов
Аргументы это просто значения, которые могут быть указаны при запуске скрипта.
Всем переданным аргументам присваивается уникальное имя равное их порядковому номеру:
Нулевой аргумент всегда равен названию файла со скриптом:
Все аргументы можно положить в именованный массив:
@
- это название массива по умолчанию, который хранит все аргументы (за исключением нулевого)
Количество переданных аргументов (за исключением нулевого) хранится в переменной #
:
Условия if else
Условия всегда начинаются с ключевого слова if
и заканчиваются на fi
:
Условий может быть сколько угодно много, для этого используется конструкция elif
, которая также как if
может проверять условия:
Обратите внимание, что после конструкций
if
иelif
всегда следует строчка с ключевым словомthen
Так же не забывайте отделять условия пробелами внутри фигурных скобок ->[ condition ]
Операторы условий
Для цифр и строк могут использоваться разные операторы сравнения. Полные их списки с примерами приведены в таблицах ниже.
Обратите внимания, что разные операторы используются с определенными скобками
Операторы сравнения для чисел
Оператор | Описание | Пример |
---|---|---|
-eq | равняется ли | if [ $age -eq 18 ] |
-ne | не равняется | if [ $age -ne 18 ] |
-gt | больше чем | if [ $age -gt 18 ] |
-ge | больше чем или равно | if [ $age -ge 18 ] |
-lt | меньше чем | if [ $age -lt 18 ] |
-le | меньше чем или равно | if [ $age -le 18 ] |
> | больше чем | if (($age > 18)) |
< | меньше чем | if (($age < 18)) |
=> | больше чем или равно | if (($age => 18)) |
<= | меньше чем или равно | if (($age <= 18)) |
Операторы сравнения для строк
Оператор | Описание | Пример |
---|---|---|
= | проверка на равенство | if [ $str = "hello" ] |
== | проверка на равенство | if [ $str == "hello" ] |
!= | проверка на НЕ равенство | if [ $str != "hello" ] |
< | сравнение меньше чем по ASCII коду символов | if [[ $str < "hello" ]] |
> | сравнение больше чем по ASCII коду символов | if [[ $str > "hello" ]] |
-z | проверка пустая ли строка | if [ -z $str ] |
-n | проверка есть ли в строке хоть один символ | if [ -n $str ] |
Так же существуют операторы для проверки различных условий над файлами.
Операторы для проверки файлов
Оператор | Описание | Пример |
---|---|---|
-e | проверяет, существует ли файл | if [ -e $file ] |
-s | проверяет, пустой ли файл | if [ -s $file ] |
-f | проверяет, является ли файл обычным файлом, а не каталогом или специальным файлом | if [ -f $file ] |
-d | проверяет, является ли файл каталогом | if [ -d $file ] |
-r | проверяет, доступен ли файл для чтения | if [ -r $file ] |
-w | проверяет, доступен ли файл для записи | if [ -w $file ] |
-x | проверяет, является ли файл исполяемым | if [ -x $file ] |
Логические операторы
Условия с оператором "И" возвращают истину только в том случае, когда все условия истины.
Существует несколько вариантов написания условий с логическими операторами
Условия с оператором "ИЛИ" возвращают истину в том случае, когда хотя бы одно условие истинно.
Арифметические операторы
Обратите внимание, что при использовании умножения с ключевым словом
expr
необходимо использовать косую черту.
Конструкция switch case
Не всегда удобно использовать конструкции if/elif для большого количества условий. Для этого лучше подойдет конструкция case:
Случай со звездочкой * отработает лишь в том случае, если не подойдет ни одно из условий выше.
Массивы
Массивы позволяют хранить целую коллекцию данных в одной переменной. С этой переменной можно удобно и легко взаимодействовать:
Обратите внимание, что элементы массива разделются пробелом без запятой.
Элементы массива можно добавлять/перезаписывать/удалять по ходу выполнения скрипта:
Цикл while
Цикл while повторяет выполение блока кода описанного между ключевыми словами do
- done
пока истино заданное условие.
Операция увеличения числа на 1 единицу называется инкриментом и для неё существует специальная запись:
Противоположная операция - декремент:
С помощью while циклов можно построчно читать различные файлы. Существует несколько способов сделать это:
Цикл until
Цикл until противоположен циклу while тем, что он выполняет блок кода описанный между ключевыми словами do
- done
тогда, когда заданное условие возвращает false:
Цикл for
Самый классический цикл:
В новых версиях Bash существует более удобный способ записи с помощью оператора in
:
Условие после ключевого слова in
в общем случае выгядит так:
START - с какого элемента начинать цикл;
END - до какого элемента продолжать цикл;
INCREMENT - на сколько увеличивать элемент после каждой итерации (по умолчанию на 1).
Цикл for можно использовать для последовательного запуска набора команд:
Ключевое слово break
останавливает выполнение цикла.
Ключевое слово continue
завершает текущую итерацию цикла и переходит к следующей.
Цикл select
Крайне удобный цикл для создания меню выбора опций:
Цикл select
очень хорошо сочетается с оператором выбора case
. Таким образом можно очень просто создавать интерактивные консольные приложения с большим количеством разветвлений:
Break и continue в циклах
Для принудительного выхода из цикла используется ключевое слово break
:
Для того, чтобы пропустить выполнение текущей итерации в цикле и перейти к следующей - используется ключевое слово continue
:
Функции
Функции - это именованные участки кода, которые могут переиспользоваться неограниченное количество раз:
Функции, так же, как и сами скрипты, могут принимать аргументы. Они имеют такие же названия, но аргументы функций видны только внутри функции, в которую они были переданы:
Локальные переменные
Если мы объявим какую-либо переменную, а затем объявим ещё одну с таким же именем, но уже внутри функции, то у нас произойдет перезапись:
Чтобы предотвратить такое поведение используются ключевое слово local
перед именем переменной, которая объявляется внутри функции:
Ключевое слово readonly
По умолчанию, каждая созданная переменная в Bash в последующем может перезаписываться. Чтобы защитить переменную от изменений можно использовать ключевое слово readonly
:
readonly
можно использовать не только в момент объявления переменной, но и после:
Тоже самое касается функций. Они так же могут быть переопределены, поэтому их можно защитить с помощью readonly
указав при этом флаг -f
:
Обработка сигналов
Во время выполнения скриптов, могут происходить неожиданные действия. Например, пользователь может прервать выполнения скрипта с помощь комбинации Ctrl + C
, либо может случайно закрыть терминал или в самом скрипте может случится какая-либо ошибка и так далее…
В POSIX-системах существуют специальные сигналы - уведомления процесса о каком-либо событии. Их список определен в таблице ниже:
Сигнал | Код | Действие | Описание |
---|---|---|---|
SIGHUP | 1 | Завершение | Закрытие терминала |
SIGINT | 2 | Завершение | Сигнал прерывания (Ctrl-C) с терминала |
SIGQUIT | 3 | Завершение с дампом памяти | Сигнал «Quit» с терминала (Ctrl-) |
SIGILL | 4 | Завершение с дампом памяти | Недопустимая инструкция процессора |
SIGABRT | 6 | Завершение с дампом памяти | Сигнал, посылаемый функцией abort() |
SIGFPE | 8 | Завершение с дампом памяти | Ошибочная арифметическая операция |
SIGKILL | 9 | Завершение | Процесс уничтожен (kill signal) |
SIGSEGV | 11 | Завершение с дампом памяти | Нарушение при обращении в память |
SIGPIPE | 13 | Завершение | Запись в разорванное соединение (пайп, сокет) |
SIGALRM | 14 | Завершение | Сигнал истечения времени, заданного alarm() |
SIGTERM | 15 | Завершение | Сигнал завершения (сигнал по умолчанию для утилиты kill) |
SIGUSR1 | 30/10/16 | Завершение | Пользовательский сигнал № 1 |
SIGUSR2 | 31/12/17 | Завершение | Пользовательский сигнал № 2 |
SIGCHLD | 20/17/18 | Игнорируется | Дочерний процесс завершен или остановлен |
SIGCONT | 19/18/25 | Продолжить выполнение | Продолжить выполнение ранее остановленного процесса |
SIGSTOP | 17/19/23 | Остановка процесса | Остановка выполнения процесса |
SIGTSTP | 18/20/24 | Остановка процесса | Сигнал остановки с терминала (Ctrl-Z) |
SIGTTIN | 21/21/26 | Остановка процесса | Попытка чтения с терминала фоновым процессом |
SIGTTOU | 22/22/27 | Остановка процесса | Попытка записи на терминал фоновым процессом |
В Bash есть ключевое слово trap
с помощью которого можно отлавливать различные сигналы и предусматривать выполнение определенных команд:
Под сигналом можно использовать его название (колонка Сигнал в таблице), либо его код (колонка Код в таблице). Можно указывать несколько сигналов разделяя их названия или коды пробелом.
Исключения: сигналы SIGKILL (9) и SIGSTOP (17/19/23) отловить невозможно, поэтому нет смысла их указывать.