Node-служба не видит переменные окружения
Приложения часто читают настройки из файла в каталоге проекта, но делают это библиотекой, а не средствами системы. Если библиотека не подключена или рабочий каталог другой, переменных нет — и служба падает с непонятным сообщением.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Файл настроек ищется относительно рабочего каталога
Библиотеки читают файл относительно текущего каталога. У службы он другой, и файл не находится.
-
Переменные заданы в профиле оболочки
Служба не читает профиль. Переменные, работающие в терминале, для неё не существуют.
-
Секреты в переменных видны в выводе состояния
Даже работающая схема с переменными имеет недостаток: значения видны любому, кто может выполнить команду просмотра свойств.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Всё, что определяет настройки службы.
systemctl show myapp.service -p Environment -p EnvironmentFile -p WorkingDirectoryСообщение приложения о недостающей настройке.
journalctl -u myapp.service -n 20 --no-pager | tail -10Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Библиотеки читают файл относительно текущего каталога. У службы он другой, и файл не находится.
- Как проверить
-
Посмотрите рабочий каталог службы.
systemctl show myapp.service -p WorkingDirectory ls -l /opt/myapp/.env 2>/dev/null
- Как исправить
-
Задайте
WorkingDirectory=каталогом проекта либо передавайте переменные черезEnvironmentFile=: второе надёжнее и не зависит от библиотек.
- Почему происходит
- Служба не читает профиль. Переменные, работающие в терминале, для неё не существуют.
- Как проверить
-
Посмотрите окружение службы.
systemctl show myapp.service -p Environment -p EnvironmentFile
- Как исправить
- Перенесите переменные в файл окружения и подключите его в unit-файле.
- Почему происходит
- Даже работающая схема с переменными имеет недостаток: значения видны любому, кто может выполнить команду просмотра свойств.
- Как проверить
-
Посмотрите, что попадает в вывод.
systemctl show myapp.service -p Environment
- Как исправить
- Для секретов используйте механизм учётных данных: они не попадают ни в окружение, ни в вывод состояния.
Пример вывода
Файл настроек не найден из-за другого рабочего каталога. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
myapp[4200]: Error: DATABASE_URL is not defined
myapp[4200]: at loadConfig (/opt/myapp/src/config.js:12:11)
$ systemctl show myapp.service -p WorkingDirectory
WorkingDirectory=
Связанные ошибки
- Переменная в unit-файле не разворачивается Запись со знаком доллара попадает в аргументы буквально. Где подстановка работает, а где нет.
- В терминале работает, а под systemd нет Самая частая жалоба: программа запускается руками, но не как служба. Полный разбор отличий окружения.
- status=200/CHDIR в systemd Код 200/CHDIR означает, что systemd не смог перейти в каталог из WorkingDirectory= до запуска программы. Причины и решение.
- Node-служба не может занять порт 80 Приложение на Node падает при привязке к привилегированному порту: как дать возможность вместо запуска от root.
- Имена разрешаются не через ту подсистему Служба не находит узел, который виден другим средствам: порядок источников разрешения имён задан иначе.
- Контейнеры не запускаются: среда выполнения не найдена Служба контейнеров работает, а запуск контейнера отказывает: нет исполняемого файла среды выполнения в пути службы.
- Служба на Python не находит зависимости Модули не импортируются: в unit-файле указан системный интерпретатор вместо интерпретатора окружения.
- Служба падает из-за локали Ошибки вида cannot change locale или искажение кириллицы: у службы другое окружение локали.
Источники
-
systemd.exec(5)
Environment= и EnvironmentFile=. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено приложением, читающим файл настроек относительно текущего каталога.