img

5 встроенных Bash-переменных, которые должен знать каждый разработчик

Используйте эти переменные командного процессора и пишите современные, простые и информативные сценарии.

icon strelka icons icons

узнай больше на курсе

Python программист с нуля
Стань разработчиком на одном из самых популярных языков программирования - Python
Укажите вашу электронную почту
Неверный адрес электронной почты
Нажимая на кнопку, вы соглашаетесь на обработку персональных данных
Готово!
Отправили доступы на вашу
электронную почту
Java-разработчик с нуля
Освойте backend-разработку и программирование на Java, фреймворки Spring и Maven, работу с базами данных и API
Укажите вашу электронную почту
Неверный адрес электронной почты
Нажимая на кнопку, вы соглашаетесь на обработку персональных данных
Готово!
Отправили доступы на вашу
электронную почту
C# разработчик с нуля
На курсе ты освоишь основы программирования на C#, включая синтаксис, объектно-ориентированное программирование и асинхронное программирование.
Укажите вашу электронную почту
Неверный адрес электронной почты
Нажимая на кнопку, вы соглашаетесь на обработку персональных данных
Готово!
Отправили доступы на вашу
электронную почту

Как правило, разработчики использую Bash для того, чтобы писать сценарии оболочки, ссылаясь при этом на другие программы, которые выступают в роли команд, и добавляя всторенные функции языка командной оболочки Bash. Вместе с тем, все пользователи Unix и Unix-подобных систем используют Bash для взаимодействия с операционной системой через терминальные программы с графическим интерфейсом. Сценарий оболочки, написанный на языке Bash, состоит из нескольких синтаксических элементов. В сценариях оболочки мы довольно часто используем такие синтаксические элементы, как параметры. В языке командной оболочки Bash параметр – это объект, который хранит некое значение. У Bash есть три типа параметров: переменные, позиционные параметры и специальные параметры. 

У переменной есть хорошо читаемое имя и несколько атрибутов, которые устанавливаются через встроенное объявление. Некоторые переменные определяются на основе общесистемных переменных среды, заданных в операционной системе. Кроме того, несколько переменных оболочки определяет командный интерпретатор Bash. И плюс ко всему, мы можем создавать как глобальные, так и локальные переменные внутри сценариев оболочки. Это зависит от наших собственных требований к разработке. 

Интерпретатор Bash предлагает несколько полезных вещей в процессе выполнения сценария, доступ к которым вы можете получить посредством переменных оболочки. В некоторых случаях мы можем повысить производительность сценария с помощью переменных оболочки, не прибегая к использованию внешних процессов. Здесь я расскажу вам о нескольких полезных переменных оболочки, которые вы можете использовать в Bash, а также приведу практические примеры. 

Проверяем версию интерпретатора Bash с помощью BASH_VERSINFO

У большей части программ командной строки есть флаг --version, который выводит на экран сведения о версии. У интерпретатора Bash тоже есть такой параметр командной строки, поэтому его пользователи могут использовать этот флаг для того, чтобы проверить сведения о версии. Допустим, что вы хотите воспользоваться более новым синтаксисом Bash с учетом версии интерпретатора или отобразить на экране сообщение о несовместимости для более старых исполнений интерпретатора Bash. 

Чаще всего переменная оболочки BASH_VERSION возвращает строку с полной версией, поэтому для начала нам нужно извлечь и основной номер версии, и дополнительный. Между тем, вы можете воспользоваться массивом BASH_VERSINFO (выпущен в Bash 2.0) для того, чтобы получить доступ ко всем частям строки с версией:

#!/bin/bash

if ((BASH_VERSINFO[0] < 5 ||
    (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] < 1) )); then
    echo "This script requires Bash 5.1 or a higher version."
    exit 1
fi

Если версия Bash, которую использует пользователь, меньше, чем 5.1, то фрагмент кода, приведенный выше, останавливает выполнение сценария. Если вам все-таки нужно вывести на экран версию интерпретатора Bash вместе с основным и дополнительным номерами, то вы можете воспользоваться BASH_VERSION вместо того, чтобы собирать отдельные части BASH_VERSINFO:

#!/bin/bash

echo "You are using Bash ${BASH_VERSION%.*}"

Фрагмент кода выше выводит на экран основной и дополнительный номера версии интерпретатора Bash, и делает он это с помощью функции расширения параметров. 

Выводим время исполнения сценария с помощью SECONDS

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

Переменная SECONDS помогает измерить время выполнения сценария и выбрать решение для случаев, описанных выше. Взгляните на сценарий ниже. Он выводит на экран время выполнения команды.

#!/bin/bash

function start_timer() {
    SECONDS=0
}

function display_elapsed() {
    echo "Task executed in $SECONDS seconds"
}

# ---- Task 1 ----
start_timer
sleep 2
display_elapsed

# --- Task 2 ---
start_timer
sleep 3
display_elapsed

Как правило, команда timeout используется для запуска команды с заранее заданным временем ожидания. Кроме того, вы можете использовать переменную SECONDS для запуска простого фрагмента сценария в течение заданного количества времени (времени ожидания), как, например, здесь:

#!/bin/bash

TIMEOUT=10

while (( TIMEOUT > SECONDS )); do
    prog=$(bc <<< "scale=1; $SECONDS / $TIMEOUT * 100")
    echo "Processing... ${prog}%"
    sleep 2
done

echo "Stopped with ${TIMEOUT}-second timeout."

Фрагмент кода, представленный выше, отлично подходит для неоднократного запуска простых задач в течение долгого времени. Эта настройка запускает двухсекундную задачу пять раз, учитывая при этом время ожидание в размере 10 секунд, и отображает на экране истекшее время выполнения в процентах:

(видео)

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

Используем PWD и OLDPWD

Все пользователи Unix и Unix-подобных систем знают, что такое команды pwd и cd. Что, если вам нужно найти текущий или предыдущий рабочий каталог в Bash-сценарии? Как правило, эти команды запускаются через отдельные процессы (дочерние оболочки), в связи с чем, когда вы используете эти команды, они прекращают интерпретацию Bash-сценария для того, чтобы создать новый процесс. Для того, чтобы получить текущий и предыдущий рабочий каталоги, вы можете воспользоваться экспортируемыми переменными PWD и OLDPWD:

#!/bin/bash

cd /home
echo "PWD -> $PWD"

cd ~- # Go to the previous directory
echo "PWD -> $PWD"
echo "OLDPWD -> $OLDPWD" # OLDPWD -> /home

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

PWD=/home

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

(видео)

Изменение PWD приводит к некоторым проблемам, скриншот автора

Используем BASH_COMMAND совместно с Trap

BASH_COMMAND сохраняет значение текущей введенной команды. Если вы попытаетесь вывести сохраненное значение этой переменной с помощью команды echo, то увидите ту же команду echo, которую вы вводили до этого. Как же можно эффективно использовать эту переменную? И для какой проблемы предназначена BASH_COMMAND

Вы можете использовать BASH_COMMAND в рамках ловушек (traps). Иными словами, с помощью команды trap вы можете получить самую последнюю команду (когда обработаете все ее ошибки). Здесь отличным примером может послужить отображение или обработка «неуспешной» команды с помощью команды trap. Взгляните на следующий фрагмент кода:

function __handle_cmd_err() {
    exit_code=$?
    echo "--------------"
    echo "ERR: '$BASH_COMMAND' command was terminated with error code $exit_code"

}

trap __handle_cmd_err ERR

Если вы добавите этот фрагмент в свой файл ~/.bashrc, и команда завершит свою работу с кодом завершения, отличным от нуля, то вы увидите код завершения процесса и строку с «неуспешной» командой:

(видео)

Использование команды trap вместе с BASH_COMMAND, скриншот автора

Проследите за правильным использованием специального параметра $?. Если вы выводите на экран строку и тут же используете параметр $? в другом операторе echo, то вы получите код завершения оператора echo, а не тот, который вы ожидаете увидеть после неудачного завершения команды. 

В примере выше BASH_COMMAND используется вместе с сигналом ERR. Но вы также можете использовать и сигнал INT для того, чтобы перехватывать прерывания клавиатуры и реализовывать операторы очистки.

Используем MACHTYPE, HOSTTYPE и OSTYPE в качестве альтернативы Uname и Arch

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

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

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

#!/bin/bash


OS="Unknown"

case "$OSTYPE" in
    linux*)
        OS="Linux" ;;
    bsd*)
        OS="BSD" ;;
    # ---
    # -- TODO: Add other OS type checks...
    # ---
esac

echo $OS

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

#!/bin/bash

gcc main.c -o myprogram-${OSTYPE%%-*}_${HOSTTYPE}

Сценарий, приведенный выше, генерирует myprogram-linux_x86_64 в системах GNU/Linux x64 и соответствующие имена двоичных файлов на других платформах.

Пожалуй, я закончу эту статью небольшим бонусным фактом о сценариях оболочки. Знаете ли вы, как проверить, является ли какая-то конкретная команда встроенной, псевдонимом или отдельным двоичным файлом?

Для этого вам нужна команда -a <command>:

(видео)

Проверка типов команд в терминале, скриншот автора

Ссылка
скопирована
Получите бесплатные уроки на наших курсах
Все курсы
icon strelka icons icons

узнай больше на курсе

Python программист с нуля
Стань разработчиком на одном из самых популярных языков программирования - Python
Подробнее о курсе
Java-разработчик с нуля
Освойте backend-разработку и программирование на Java, фреймворки Spring и Maven, работу с базами данных и API
Подробнее о курсе
C# разработчик с нуля
На курсе ты освоишь основы программирования на C#, включая синтаксис, объектно-ориентированное программирование и асинхронное программирование.
Подробнее о курсе
Фронтенд-разработчик с нуля
Погрузитесь в мир веб-разработки, освоив основные инструменты работы: HTML, CSS, JavaScript
Подробнее о курсе
Разработка приложений на Flutter и Dart
Научись создавать кроссплатформенные приложения на Flutter, освой язык Dart
Подробнее о курсе
Автоматизированное тестирование на Python
Изучите автоматизацию тестирования на Python чтобы стать востребованным специалистом
Подробнее о курсе
Еще по теме:
img
SQL или NoSQL, вот в чём вопрос! И как раз с этим вопросом мы поможем сегодня разобраться. Что использовать в каких случаях, где есть какие преимущества и как возможно использовать их все вместе.
img
Вебхуки позволяют различным системам обмениваться данными в реальном времени. В этой статье мы разберём, что такое вебхук, как он работает, где и зачем его использовать, а также как настроить.
img
Redis — один из самых популярных инструментов для хранения данных. В статье разбираем, что такое Redis и как его можно использовать.
img
Маска подсети помогает определить, какие устройства находятся в одной сети, а какие – за её пределами. В этой статье разберём, что такое маска подсети, зачем она нужна и как её использовать.
Весенние скидки
30%
50%
60%
До конца акции: 30 дней 24 : 59 : 59