Введение в Bash. Принцип работы, популярные команды и создание скриптов.

Для успешного использования Linux необходимо понимать специфику его функционирования и овладеть навыками работы с командной строкой. Это позволит автоматизировать множество задач и значительно ускорить процесс работы.

В данном тексте мы обсудим стандартный командный интерпретатор, который присутствует в большинстве дистрибутивов Linux - Bash. Мы рассмотрим основные принципы его функционирования, исследуем наиболее популярные команды и применим полученные знания на практике.

Что такое Bash

BASH (Bourne-Again Shell) — один из наиболее распространенных командных интерпретаторов в UNIX-подобных системах, а также язык интерфейса командной строки, который поддерживает использование переменных, массивов, циклов, функций, арифметических операторов, операций ввода-вывода и прочих возможностей.

Основная особенность BASH — возможность создания сценариев для автоматической обработки повторяющихся задач. Постигнув работу с этим интерфейсом, вы сможете:

  • Быстро переименовывать все файлы в каталоге

  • Генерировать случайные пароли

  • Создавать и отправлять отчеты по email

  • Проверять и обновлять систему и программы

  • Очищать кэш браузера одной командой

В UNIX-системе обычно доступны различные типы shell-оболочек. Помимо Bash, стоит упомянуть такие, как csh (C shell), ksh (Ksh shell) и zsh (Z shell).

Давайте проясним термины Unix и Shell.

Большинство современных операционных систем, кроме WINDOWS, основаны на UNIX. Это, в том числе, дистрибутивы Linux, macOS, iOS и Android. UNIX характеризуется модульной архитектурой, в которой каждая функция выполняется отдельной программой, а взаимодействие между ними происходит через общую файловую систему. Shell используется для управления этими программами и исполнения команд.

Shell (оболочка) — это программа, обеспечивающая взаимодействие пользователя с системой. В командной строке вы вводите команды, которые оболочка интерпретирует, вызывает соответствующие программы и отображает результаты. Команды могут подаваться не только в текстовом режиме, но и считываться из файла, называемого shell-скриптом или оболочкой shell-программы.

Для обеспечения интерфейса командной строки в операционных системах используются командные интерпретаторы. Они могут представлять собой самостоятельные языки программирования со своим синтаксисом и функциональными возможностями.

Самые популярные командные интерпретаторы — это Terminal (Linux, macOS) и Konsole (Windows). Именно с их помощью можно взаимодействовать с командной оболочкой shell, которая будет принимать специальные команды и передавать их на выполнение операционной системе.

Основы Bash

Для начала — три главных особенности, с которых стоит начать знакомство с Bash:

  1. Написание любого скрипта нужно начинать со строки: #!/bin/bash. После символа #! следует путь к bash-интерпретатору. Вы можете узнать путь к нему (возможно, интерпретатор был установлен в другое место) с помощью команды whereis bash.
  2. Комментарии и примечания нужно указывать после символа # (кроме первой строки, где мы указываем путь к bash-интерпретатору)
  3. Bash не имеет строгой системы типов

Тип данных определяется в зависимости от контекста использования переменной и ее содержимого. Bash устанавливает следующие правила для именования переменных:

  • Имена переменных должны начинаться с латинской буквы (в верхнем или нижнем регистре) или символа подчеркивания.

  • В имени переменной запрещено использовать пробелы или специальные символы.

  • Регистр букв в именах переменных учитывается. Переменные name1 и Name1 считаются разными.

  • Рекомендуется избегать использования ключевых слов Bash в качестве названий переменных

Создаем виртуальный сервер и подключаемся к нему

Чтобы учиться на практике, нам нужна соответствующая среда. Если вы используете компьютеры с системой Linux или macOS, то можете все сделать локально. В нашем случае компьютер на базе Windows, поэтому мы создадим виртуальный сервер на базе Ubuntu 20.4. Для этого нам нужно зайти в Панель 1cloud и перейти в раздел «Виртуальный сервер».

Нажимаем на кнопку «Создать сервер» и далее выбираем, какой дистрибутив Linux установим на свой сервер. Ниже настраиваем нужную нам конфигурацию и жмем «Заказать».

Осталось подождать несколько минут и мы можем подключиться к нашей виртуальной машине. Для этого есть два варианта: использовать программу putty  или подключиться по SSH. В данном случае мы выберем второй вариант.

Чтобы начать, откройте командную строку и введите «ssh root@» с указанием IP-адреса сервера. После этого появится строка для ввода пароля. Обратите внимание, что символы пароля не будут отображаться.

IP-адрес и пароль вашего виртуального сервера можно найти на странице с параметрами сервера.

После указания IP-адреса и ввода пароля для удаленного сервера, вы увидите приветствие от Ubuntu. Здесь указаны ссылки на документацию и поддержку, актуальная информация о вашей системе и последних обновлениях. Последние две строки содержат информацию о вашем последнем входе в систему и приглашение Shell. В разных дистрибутивах строка Shell может отображаться по-разному, но обычно она выглядит как имя_пользователя@имя_компьютера и знаки ~#.

С приглашения Shell будет начинаться каждая новая строка. Если вы хотите изменить содержимое этой переменной введите PS1= и после знака равенства напишите то, что будет выводиться в начале строки. Например, мы введем line:. После перезапуска Терминал вернется к своим исходным настройкам.

Теперь мы можем приступать к работе. Для начала изучим несколько простых команд.

Команды Bash

Команда Bash — наименьшая единица кода, которую оболочка может выполнить самостоятельно. С их помощью bash понимает, что нужно сделать. Обычно оболочка принимает от пользователя одну команду и возвращается после ее выполнения.

  • echo — выводит указанную информацию.
  • date — отображает текущие время и дату.
  • cal — календарь на текущий месяц.
  • clear (или сочетание CTRL+L) — очищает окно терминала.

Как видите, все достаточно просто и легко. Значит, мы можем идти дальше и знакомиться с более сложными сценариями работы с Bash.

Теперь разберемся, как использовать основные команды для работы с файловой системой.

Работа с файлами

В Bash вся файловая система состоит из файлов и директорий. Директория - это аналог папки, которая также может содержать в себе файлы и другие директории, которые называются поддиректориями. В свою очередь, поддиректория также может содержать в себе другие файлы и поддиректории. Так образуется иерархия директорий, которое называют деревом (tree). Чтобы получить доступ к каталогу или файлу, необходимо пройти через последовательность узлов в этой древовидной структуре. Пути разделены между узлами структуры с помощью слеша /.

Самая главная, верхняя, директория называется root и обозначается символом /.

Рассмотрим основные команды для работы с директориями.

  • pwd — указывает на текущую рабочую директорию.
  • cd — перемещение между директориями.
  • mkdir — создание новой директории.
  • ls — отображение содержимого текущей рабочей директории.

Под текущей рабочей директорией подразумевается та директория, из которой выполняются команды в настоящий момент. То есть с помощью команды cd можно перейти в другую директорию, размещенную в текущей.

Используя команду cd мы можем указать абсолютный и относительный путь.

Абсолютный путь — это путь, который начинается от корневой директории /. Например: cd /root/dmkuk.

Относительный путь — это путь, который начинается от текущей рабочей директории. То есть так, как мы сделали в примере выше: сначала ввели pwd и узнали в какой директории находимся, а затем с помощью команды cd перешли в следующую.

Как видите, передвигаться вверх по дереву директорий довольно просто, а вот обратно не очень — нужно указывать абсолютный путь вплоть до нужной директории. Чтобы упростить этот момент, существуют специальные символы.

. — текущая директория

.. — родительская директория

~ — домашняя директория текущего пользователя

Добавим в наш пример выше обратный путь к домашней директории.

Переменные

Для создания переменной, которая хранит определенное значение, достаточно указать ее название, знак = и нужное значение после него. Например, Number=16. В качестве значения можно использовать как числа, так и строки. Однако для того, чтобы объявить переменную строкового типа, состоящую из нескольких слов, нужно заключить ее в кавычки — одинарные или двойные. Разница между ними лишь в том, что при двойных кавычках мы можем использовать итерполяцию — обращение к другим переменным.

Когда мы хотим обратиться к нашей переменной, достаточно ввести команду echo и указать имя переменной со знаком $.

Важно понимать, что таким образом мы создаем локальные переменные, т.е. такие, которые доступны только в рамках данного окна shell. Когда мы введем другую команду, внутри нее уже не будет доступа к локальным переменным. Чтобы сделать глобальную переменную (на языке Unix - Environment variables, переменная окружения) нужно воспользоваться командой export.

Если мы захотим посмотреть, какие у нас в целом имеются переменные окружения, мы можем воспользоваться командой printenv.

В этом списке мы можем увидеть и другие переменные окружения, которые уже были установлены. Например, переменная Shell, которая указывает, где оболочка shell находится по умолчанию. Здесь же мы можем увидеть переменную pwd. То есть, когда мы используем команду pwd, на самом деле мы просто выводим значение этой переменной окружения.

Еще одна важная переменная окружения в контексте работы Unix — PATH. Остановимся на ней подробнее.

Переменная PATH используется каждый раз, как мы вбиваем любую команду. Все команды хранятся в виде обычных файлов. Для того, чтобы найти нужный файл, операционная система использует переменную окружения PATH и ищет последовательно в каждой из директорий файл нужной команды.

Соответственно, чтобы создать новую команду, необходимо положить ее в одну из указанных директорий, либо добавить новую также с помощью команды export.

Теперь пришло время начать работать с файлами и их содержимым.

Чтение текстовых файлов

Для чтения текстовых файлов существует перечень стандартных команд.

  • cat — позволяет вывести на консоль все содержимое файла.
  • nl — также выводит все содержимое файла, но кроме этого нумерует строки и позволяет проводить дополнительные манипуляции с ними.
  • head — отображает первые 10 строк файла.
  • tail — отображает последние 10 строк файла.
  • less — позволяет понемногу считывать большой файл.

Если мы хотим на практике посмотреть, как работают эти команды, то для начала нам нужно создать текстовый файл и что-то написать в нем. Для этого есть несколько способов. Рассмотрим два из них.

Команда touch. Это стандартная команда для создания пустых файлов. После ее ввода через пробел нужно указать название файла. Если вам нужно создать несколько файлов одновременно, просто введите несколько названий, отделяя их пробелом. Далее созданный файл можно отредактировать в любом текстовом редакторе (о которых поговорим ниже).

Перенаправление вывода (>).  Второй способ — оператор перенаправления вывода. Чтобы создать с помощью него файл, достаточно ввести знак > и через пробел указать имя файла. Важно быть внимательным при использовании этого способа, т.к. если файл уже существует, то он будет перезаписан.

В связке с командой cat он позволяет создать пустой файл и сразу внести в него нужную информацию, без использования текстового редактора. Это удобно, если необходимо создать текстовый файл с небольшим содержимым.

После ввода команды написать текст можно прямо в терминале. Чтобы завершить ввод текста и сохранить изменения, нужно воспользоваться комбинацией Ctrl + D.

Что с типами данных?

В Bash отсутствует строгая типизация, как в некоторых других языках. Bash-переменные являются строками, но, в зависимости от контекста, допускается целочисленная арифметика. Фактором, определяющим тип данных, является содержимое переменной.

Строки (strings) — последовательность символов, заключенная в кавычки. Как мы уже говорили, Bash допускает написание строк в одинарных или двойных кавычках.

Числа (numbers) — целочисленные значения. Bash поддерживает арифметические действия с целыми числами. Выражения начинаются со знака $ и обрамляются двойными круглыми скобками.

Массивы (arrays) — упорядоченные коллекции данных, доступ к которым осуществляется по индексу.

Логические значения (boolean) — используются для проверки выполнения условий. Могут принимать только два значения — истинное или ложное.

Итак, мы почти готовы к созданию наших первых скриптов на Bash. Осталось только установить текстовый редактор.

Какой текстовый редактор выбрать?

Текстовых редакторов есть большое множество. Для локальной работы можно использовать абсолютно любой редактор. В случае работы на удаленном сервере через SSH рекомендуем использовать эти:

  • vim
  • nano
  • mcedit

Знакомство с vim может быть достаточно сложным, однако после того, как вы его освоите, он станет для вас незаменимым инструментов. Подробно о работе в этом текстовом редакторе вы можете прочитать в нашей статье из раздела «Помощь». Сегодня же мы воспользуемся редактором nano, который прост и удобен в использовании.

Nano предустановлен в большинстве дистрибутивов Linux. Если вдруг у вас его нет, то установить его можно в два этапа.

Сначала обновите репозитории apt:

sudo apt update

После установите Nano. Для разных дистрибутивов команды по установке могут отличаться, но их можно просто найти в интернете. Для Ubuntu команда выглядит следующим образом:

sudo apt install nano

Открывается файл с помощью простой команды nano имяфайла. Откроем таким образом недавно созданный нами текстовый файл demo_file.txt.

Открывается окно редактора, в котором мы видим содержимое файла (если в нем уже что-то было записано) и снизу основные команды и соответствующие им сочетания клавиш (знак ^ означает Ctrl). Сочетание Ctrl+X сохранит содержимое и закроет окно редактора, а если нам нужно сохраниться без выхода, стоит использовать сочетание Ctrl+O.

if-then-else

Ветвление if-then-else позволяет не только проверить условие, но и выполнить определенный набор команд при истинном условии, и другой набор команд при ложном.

Для выполнения более сложных задач используется конструкция elif, которая позволяет проверить дополнительное условие. Если же необходимо проверить одно условие, используется конструкция if-then. В этом случае команда будет выполнена только при истинном условии.

Далее мы продолжим создавать скрипты уже в редакторе. Для этого создадим новый файл с разрешением .sh.

Напишем скрипт приветствия, соответствующего указанному имени. Помним, что любой скрипт в Bash должен начинаться со строки #!/bin/bash.

Итак, разберем, что мы написали.

  1. Открыв ветвление конструкцией if мы задали первое значение переменной. Эти значения мы указываем в качестве аргумента после имени скрипта. $0 — всегда означает имя исполняемого скрипта, $1 — следующий за ним аргумент, $2 — следующий и т.д. В нашем случае скрипт будет иметь вид имяскрипта аргумент, поэтому нам достаточно только одного аргумента. Внутри кавычек [] важно ставить пробелы в начале и конце, иначе условие не будет работать.

  2. После того, как мы задали первое значение переменной, с помощью команды echo мы указываем действие, которые будет совершено, если условие окажется верным.

  3. Далее с помощью конструкции elif аналогичным образом создаем второе условие и соответствующее ему действие.

  4. Теперь вводим еще одно условие — когда не введен ни один аргумент. $# — количество аргументов без учета имени скрипта. В нашем случае мы указали -lt 1 что означает меньше одного (lower than 1). Получается, конструкция $# -lt 1 означает количество аргументов меньше одного.

Циклы

Циклы в Bash позволяют повторять набор команд много раз, пока не будет выполнено определенное условие.

  • for — используется для итерации по элементам списка или диапазону значений.
  • while — позволяет выполнять набор команд, пока определенное условие остается верным.

Посмотрим на практике, как они работают. Для этого создадим новый скрипт под названием myscript2.sh.

В этом примере мы сначала задали значение нашей переменной, а затем внутри цикла while указали, что если значение переменной будет меньше 10, нужно увеличивать ее на 1. В результате получаем вот такой скрипт:

Цикл for является основной конструкцией для обработки массивов. Поэтому приведем пример именно с использованием элементов массива.

В результате мы получим очень простой список:

Функции

Функции в Bash позволяют выполнять блоки кода повторно без необходимости каждый раз вводить весь код заново.

Внутри функции можно использовать обычные команды Bash, а также другие функции. Когда функция вызывается, она выполняется так, как будто весь ее код был вставлен в то место, где она вызвана. В качестве примера создадим функцию, которая выводит числа от 1 до 10.

Важная особенность — функцию необходимо объявить до того, как она будет вызвана. Вызвав нашу функцию мы увидим следующий результат:

Заключение

Подавляющее большинство приложений, особенно на Java, разрабатываются и разворачиваются на UNIX-системах. Поэтому, рано или поздно, вам все-таки придется столкнуться с Bash. Как видите, это гибкий язык и его достаточно просто изучить. Надеемся, наш текст помог вам разобраться в большинстве основных элементов Bash, и теперь вы сможете легко и быстро автоматизировать свои рутинные процессы.