Напишите современные, простые, информативные сценарии оболочки с этими переменными оболочки.

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

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

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

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

Большинство программ CLI обычно поставляются с флагом --version, который выводит сведения о версии. Интерпретатор Bash также реализует этот флаг командной строки, поэтому пользователи 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."

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

Использование 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

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

Использование BASH_COMMAND с ловушками оболочки

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

Вы можете использовать BASH_COMMAND внутри ловушки-оболочки. Другими словами, вы можете получить самую последнюю команду, когда обработаете ее ошибки с помощью команды 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 и команда завершится с ненулевым кодом выхода, вы увидите код выхода процесса и строку неудачной команды:

Обязательно правильно используйте специальный параметр $? — если вы отобразите строку и используете $? непосредственно в другом операторе 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 возвращает сведения о компьютерной системе, включая архитектуру системы, тип компьютера и операционную систему. Эти переменные можно использовать для динамического создания бинарных имен для конкретных платформ в разных системах. Посмотрите на следующий сценарий оболочки, который компилирует программу на C:

#!/bin/bash

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

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

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

Используйте type -a <command>:

Спасибо за прочтение.

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу