Перейти к содержанию

Переменные окружения

Полей два, потому что они про разное. env_file общий для команды — он лежит в репозитории или в .gitignore. env — точечная правка: мне сейчас надо поднять логи на одном профиле.

[profiles.api]
adapter = "dlv"
program = "cmd/api"
env_file = ".env"
env = { LOG_LEVEL = "debug", ROOT = "${root}" }

Приоритет

От слабого к сильному: унаследованное окружение → env_fileenv.

Написанное в профиле явно выигрывает всегда. Иначе DATABASE_URL, экспортированный в шелле полгода назад, молча побеждал бы конфиг, и ничто на экране об этом не сказало бы.

Отсутствующий env_file — ошибка

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

Автоподхвата нет

Лежащий рядом с кодом .env сам по себе не подключается. Неявная подстановка окружения — сюрприз, который потом дорого отлаживать, а строчка env_file = ".env" занимает столько же места и не врёт.

Формат .env

Поддерживается сознательно узкое подмножество:

# комментарий
DATABASE_URL=postgres://localhost/app
export PORT=8080
GREETING="hello  world"     # кавычки сохраняют пробелы
MULTI="a\nb"                # в двойных кавычках работают \n \r \t \\ \"
LITERAL='a\nb'              # в одинарных значение берётся буквально
HASH=a#b                    # комментарий начинается только с ` #`
EMPTY=

Интерполяции ${VAR} и многострочных значений нет. У .env нет стандарта, у каждой библиотеки своя семантика подстановок, и расхождение «у нас подставилось, а в проде нет» отлаживается дороже, чем явная ошибка. Строка, которая не разобралась, останавливает запуск и называет свой номер.

При повторяющемся ключе выигрывает последнее вхождение — как в shell.

Секреты в логи не попадают

Значения env никогда не появляются ни в логе, ни в панели Logs: тела DAP-запросов не печатаются. Это инвариант, а не побочное свойство — трассировку запросов нельзя расширять, не вычистив предварительно значения env.

По той же причине в сообщении о долгом запросе из тела берутся только mode и program.

PHP — исключение

К PHP env и env_file не применяются. Адаптер ничего не запускает — он слушает DBGp-порт, а PHP-процесс поднимает PHP-FPM, Docker или запуск из CLI. Передавать окружение попросту некому.

Задавайте его там, где PHP действительно стартует: в docker-compose.yml, в конфиге пула FPM, в .env контейнера. См. Языки → PHP.

Частые случаи

Приложение не читает .env само

Если переменные раньше приезжали от direnv или расширения редактора, а не от чего-то вроде godotenv.Load(), рабочий каталог не поможет — нужен явно названный файл:

[profiles.api]
adapter = "dlv"
program = "cmd/api"
env_file = ".env"

Монорепа с общим .env выше корня

# services/api/.bugsaur/config.toml
[profiles.api]
adapter = "dlv"
program = "."
env_file = "../../.env"

Переменные, которые выставляет cargo run, а прямой запуск нет

env = { CARGO_MANIFEST_DIR = "${root}" }

См. Языки → Rust.