Переменные окружения процесса

Linux symbol

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

Переменные окружения процесса

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

Проблема

Приложения могут взаимодействовать с переменными окружения, например извлекать из них полезные данные, секреты, параметры конфигурации. Это особенно актуально для процессов CI/CD, которые часто запускаются в контейнерах.

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

Решение

Для любого пайплайна CI/CD первой командой я всегда вывожу список переменных окружения:

Примечание: не беспокойтесь о том, что в переменных могут быть секреты. Например GitHub их автоматически фильтрует (см. Accessing your secrets), но все же не стоит забывать о потенциальных уязвимостях (см. Security hardening for GitHub Actions).

Если вы работаете с докер-контейнером, достаточно зайти в него:

далее выполнить ту же команду – env или printenv.

Любой процесс в операционной системе также запускается с определенными переменными окружения. ОС хранит информацию о запущенных процессах в специальном каталоге (/proc), из которого можно вытащить в том числе данные о переменных окружения. Используйте для этого однострочник:

Где <pid> это PID процесса. Посмотреть можно с помощью обычного top или ps aux. Также увидеть переменные окружения процесса можно и обычным ps:

А теперь поговорим о примерах ситуаций, когда это может пригодиться.

Пример

Я использовал простейший пайплайн для сборки Java-приложения в GitHub Actions. Первым делом после клонирования репозитория нужно было установить требуемую версию Java. Для github-hosted раннеров это работало отлично, но проблемы начались при переходе на self-hosted раннеры. Вот пример пайплайна:

Примечание: GitHub предоставляет возможность добавления своих раннеров к проекту. Это особенно актуально для приватных проектов, которым использование ресурсов GitHub ограничено. Также это может пригодиться для проектов, требующих больших ресурсов, ведь бесплатный максимум это 7Gb RAM/2vCPU. Раннер добавить очень просто, у меня даже есть об этом статья – Установка GitHub runner.

Я получал очень странную ошибку, которая утверждала, что версия Java не передавалась:

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

Ниже в логах был пример команды docker exec. Экшн использовал её для установки Java:

Команда содержала интересные переменные с дефисом в имени, например INPUT_JAVA-PACKAGE или INPUT_JAVA-VERSION. Если попробовать задать переменную с таким именем, то оболочка будет ругаться:

Кажется проблема именно в этом, однако это ошибочные рассуждения, ведь на дефолтных раннерах все работало и в таком виде.

Примечание: хочется отметить, что переменные с дефисом в имени на самом деле разрешены, см Can shell variable name include a hyphen or dash (-)? Просто оболочка их не принимает.

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

Проблема пряталась в запуске docker через обертку в виде bash-скрипта, которая не пропускала необходимые переменные окружения. Таким образом запускаются приложения, установленные через Snap в Ubuntu. Подробнее дискуссию можно почитать в задаче Java-version is not specified on self-hosted but ok on github-runner.

Разумеется проблема решилась переустановкой Docker через обычный apt, а в личной копилке добавилось причин не использовать Snap. Хоть и пришлось потратить некоторое время на дебаг, но опыт получился интересным. Пишите, если вдруг возникают сложности с Linux. Всем спасибо, всем успехов!

Яндекс.Метрика