Знакомьтесь, Basy — мой инструмент с открытым исходным кодом для упаковки скриптов Bash.

Каждый проект начинается с потребности или идеи. В моем случае меня тронула сложность разбора аргументов в bash-скриптах и ​​совместного использования самих скриптов. Большинство разработчиков, которые пишут сценарии bash, хранят их на своем локальном ПК и, при необходимости, копируют/вставляют файл и изменяют содержимое перед его запуском. Почему?

В мире, где у каждого языка есть свой менеджер пакетов, а у каждого инструмента есть команда help для описания аргументов, такое поведение кажется очень устаревшим. В любом случае, если вы посмотрите на возможности, вы согласитесь со мной, что вариантов не так много. В скрипте Bash нет никакого менеджера пакетов, и нет стандартной библиотеки для разбора аргументов (скриптов можно найти много, но без менеджера пакетов ими сложно пользоваться).

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

Каковы преимущества Баши?

Вы можете написать файл YAML, содержащий метаданные скрипта и сам скрипт (можно встроить или сохранить извне), как в следующих фрагментах:

В манифесте YAML вы объясняете имя и описание команды, а также параметр. Как видите, параметры можно использовать прямо в скрипте как обычные переменные.

Наконец, вы можете запустить скрипт следующим образом:

Как видите, сложность разбора аргументов устранена, и теперь у вас есть автономные файлы (пакеты), которыми вы можете поделиться с другими. Красиво, нет? В следующей главе мы увидим, как устроена архитектура Баши, прежде чем углубиться в технические детали.

Как работает Баши в целом

На следующем рисунке показано, как работает Bashy:

На предыдущей диаграмме мы видим три основных потока:

  • Добавить репозиторий (красный поток): пользователь добавляет репозиторий скриптов в локальную базу данных (вы можете скачать скрипты из Интернета или добавить файлы со своего ПК). После этого шага ваша база данных содержит все данные для скрипта и может их запускать.
  • Справка (синий поток): пользователь может взаимодействовать со сценарием Bashy, чтобы получить список всех команд, зарегистрированных в репозиториях.
  • Выполнение (зеленый поток): Теперь, когда внутренняя база данных содержит всю информацию о сценарии, который необходимо запустить, Баши может проанализировать аргумент и передать его сценарию. Этот шаг полностью прозрачен для пользователя.

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

  1. Механизм синтаксического анализа аргументов
  2. Движок интерпретаторов
  3. Зарегистрировать команду глобально

Просто перейдите в следующий раздел!

Механизм синтаксического анализа аргументов

Аргумент синтаксического анализа является одним из наиболее важных моментов в управлении сценариями Bash и ядром этого приложения, поэтому он заслуживает наибольшего внимания. В любом случае, принцип очень прост. Я использую urfave/cli, консольную библиотеку разбора, которая позволяет анализировать аргументы, объясняя структуру команды. Каждая команда имеет связанную функцию, которая принимает проанализированные входные данные и выполняет определенные действия. Пример использования этой библиотеки приведен в следующих фрагментах:

В предыдущем примере есть флаг lang со значением по умолчанию english, который можно использовать внутри функции, набрав cCtx.String("lang").. Баши делает то же самое, но считывает список команд и параметров из внутренней базы данных. Реализация показана в следующем фрагменте:

Действие, обрабатывающее весь запрос, реализуется следующим фрагментом кода:

По сути, все строки скрипта объединяются. Баши добавляет к команде, встроенной в файл YAML, возможный внешний скрипт, затем создает карту ключ/значение с параметрами и вызывает служебный метод ExecuteCommand, который добавляет определение переменной поверх скрипта и запускает сам скрипт.

Движок интерпретаторов

После того, как я запустил Basy, я понял, что он может запускать любой скрипт, не только bash. Итак, следующим шагом было добавление возможности определить любой другой интерпретатор сценариев, чтобы позволить любому пользователю управлять своими сценариями с помощью bashy независимо от используемого им языка программирования. Определение интерпретатора представляет собой простой файл YAML. В следующем фрагменте вы можете увидеть определение движка Nodejs:

Файлы YAML содержат два интерпретатора, разделенных знаком ---. Вы можете видеть, что они очень похожи: оба являются определением интерпретатора Nodejs, но один для Windows, а другой для Linux. Это связано с тем, что у вас могут быть разные шаги установки в зависимости от ОС или доступности (например, у вас не может быть чистого bash в Windows или консоли Windows в Linux).

Анатомия переводчика очень проста. У вас есть следующее:

  • name: имя переводчика. В вашем скрипте YAML вы можете объяснить, какой интерпретатор его использует.
  • variabletemplate: как определяется переменная. Например, в bash у вас есть VARIABLE=VALUE, но в JavaScript var variable=VALUE; $name и $variable являются заполнителями для имен параметров, взятых из определения скрипта, и фактического значения во время выполнения.
  • installscript: это строки скрипта, используемые для установки интерпретатора. Например, для Ubuntu у нас есть apt install nodejs -y. Для поддержки всех дистрибутивов Linux я использую прием добавления нескольких строк, по одной для каждого менеджера пакетов, который активируется наличием самого менеджера пакетов. Это привело к повторению этого шаблона [[$command -v packagemanagername ]] || {packcagemanager args}.

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

Зарегистрировать команду глобально

В любом современном менеджере пакетов есть команда с «глобальной» опцией, которая глобально регистрирует исполняемый файл. Баши делает то же самое. Вы можете вызвать свой скрипт, набрав bashy your_script args или напрямую your_script args . Но как это возможно? Я использую следующий трюк:

  1. Во время установки я добавляю к переменной $PATH папку bin внутри BASHY_HOME (обычно /home/username/.bashy/bin ).
  2. Всякий раз, когда вы импортируете скрипт в Bashy, я создаю файл в папке bin с тем же именем, что и команда. Таким образом, этот файл виден оболочке и может быть запущен пользователем.
  3. Содержимое скрипта представляет собой обычный скрипт sh (или скрипт cmd в Windows), который оборачивает вызов bash чем-то вроде:
bashy {script name} "@$@".

Заключение

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

Наконец, вот несколько ссылок на статью: