kbool: классы в духе Free Pascal и модульная система для bash-скриптов
Вышла первая версия kbool 0.1.0 — инструмента, который привносит в bash-скрипты модульность, классы и библиотеку классов, знакомых по Free Pascal и Delphi. Проект распространяется под лицензией MIT и доступен на GitHub. Он предназначен для тех случаев, когда переписать скрипт на Python невозможно, а поддерживать тысячи строк bash становится всё труднее.
Проект kbool, опубликованный на GitHub под лицензией MIT, представляет собой набор инструментов для организации bash-скриптов по образу и подобию Free Pascal. Первая версия 0.1.0 включает пять git-репозиториев: корневой и четыре подмодуля — kkore, kklass, kcl и ktests. Разработка велась с активным использованием ИИ, и в репозитории есть отдельный раздел, поясняющий, как проверялся код и какие метрики при этом использовались. Автор проекта стремился решить две основные проблемы больших bash-скриптов: разрастание кода и переносимость между разными платформами.
Скрипт на bash часто начинается с двадцати строк, но через пару лет превращается в две тысячи строк с десятками функций и глобальными переменными, которые конфликтуют между собой. Подключение библиотек через source "$(dirname "$0")/lib/…" и постоянное использование $(…) для возврата значений из функций становятся обременительными. Переписать всё на Python можно не всегда: скрипт может жить в среде, где гарантированно есть только bash и базовые утилиты, или его поддерживают люди, пишущие исключительно на bash. Вторая проблема — переносимость: sed -i, stat -c, date -d, grep -Z, \b в регулярных выражениях и nc -l ведут себя по-разному на Ubuntu, Alpine с busybox, FreeBSD, macOS и в Git-bash на Windows. Скрипт, который год работал на одной машине, ломается на соседней.
kbool предлагает решение, заимствуя привычки из Free Pascal: модули, подключаемые по имени через uses, классы, объявляемые как class … end, и библиотеку классов со знакомыми именами TStringList, TDictionary, TIniFile, TRegEx. Классы объявляются в стиле паскалевского interface: сначала структура, затем тела методов как обычные функции bash, и наконец вызов build. Например, класс TCounter объявляется с полями Name и Count, конструктором Create, методами Add и Report. Тела методов — настоящие функции, поэтому редактор их подсвечивает и не нужно экранировать кавычки внутри строк. Внутри тела поля — обычные переменные, а функция возвращает значение в переменную RESULT и печатает его только внутри $( ). Это сделано для снижения накладных расходов: подстановка $( ) порождает fork, а fork дорог. Наследование и вызов родителя реализованы так, как ожидает человек, писавший на Delphi: class TDog : TAnimal public var Breed constructor Create override proc Speak end, а в теле конструктора можно вызвать inherited. Все методы виртуальные, а override — это проверка при сборке, что у предка такой метод есть.
Библиотека классов kcl включает 29 модулей: порты классов FPC и Delphi (TList, TStringList, TDictionary, TIniFile, TPath, TRegEx, DateUtils, Math и другие), обёртки над утилитами командной строки (TGrep, TSed, TAwk, TFind, THead, TTail) и небольшой HTTP-сервер. Модули подключаются по имени, повторное подключение ничего не делает. У всех модулей kcl один контракт: значение возвращается в RESULT, а не в stdout; код возврата 0 — успех, 1 — «нет» или «не найдено» (молча, без сообщений), 2 — неправильный вызов; модули работают под set -eu и не делают fork на горячих путях. Отклонения от FPC перечислены для каждого модуля в его README — например, TRegEx работает на POSIX ERE из bash, а не на PCRE, поэтому ленивых квантификаторов и lookaround нет. Для работы требуется bash 5.1 или новее; POSIX sh и старые bash не поддерживаются: kbool.sh проверяет версию первым делом и отказывается работать с кодом выхода 2 и одной строкой в stderr, а не падает на середине загрузки.
В качестве демонстрации возможностей в examples/notes.sh приведён HTTP-сервис заметок объёмом около 175 строк кода без комментариев и пустых строк. Он использует три модуля библиотеки и показывает идею: обработчики запросов выполняются в том же процессе bash, что и сервер, поэтому объекты живут между запросами. Класс TNotes содержит конструктор, деструктор и методы для работы с заметками: Help, List, Add, Show, Remove, Search, Quit, NotFound. Заметки хранятся в INI-файле через TMemIniFile, поэтому переживают перезапуск. Поиск ищет слово целиком, без учёта регистра, через TRegEx и \b. Этот пример прогоняется тестами как есть, что подтверждает работоспособность подхода.
Для российского рынка и сообщества разработчиков kbool может быть интересен в первую очередь тем, кто поддерживает большое количество bash-скриптов в условиях ограниченного набора инструментов. Например, в средах с минималистичными контейнерами (Alpine) или на устаревших системах, где установка Python или других интерпретаторов нежелательна. Подход, знакомый по Free Pascal и Delphi, может снизить порог входа для разработчиков, имеющих опыт в этих языках. Однако стоит учитывать, что проект молодой (версия 0.1.0) и его стабильность ещё предстоит проверить. Конкурирующими решениями являются такие инструменты, как bash-фреймворки (например, Bash Infinity) или переход на Python, но kbool предлагает уникальное сочетание модульности и классов без смены языка. Открытыми вопросами остаются поддержка сообщества, развитие документации и возможные ограничения производительности из-за использования fork при вызовах функций. Дальнейшие планы автора не раскрыты, но проект открыт для вкладов и уже доступен для изучения и использования.