Служба на Python не находит зависимости
Окружение Python — это не только каталог с пакетами, но и свой интерпретатор. Указание системного интерпретатора в unit-файле означает запуск без пакетов окружения, и служба падает на импорте — хотя в терминале после активации окружения всё работает.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Указан системный интерпретатор
Системный интерпретатор не видит пакеты окружения. Импорт отказывает.
-
Окружение создано для другой версии интерпретатора
После обновления системного интерпретатора окружение может перестать работать: ссылки внутри указывают на исчезнувшую версию.
-
Изоляция службы закрывает путь к окружению
Параметры защиты системы делают каталог недоступным, и запуск отказывает с кодом исполнения.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Какой интерпретатор запускается на самом деле.
systemctl show myapp.service -p ExecStartВерсия интерпретатора окружения.
/opt/myapp/venv/bin/python -V 2>&1Сообщение об ошибке импорта.
journalctl -u myapp.service -n 20 --no-pagerРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Системный интерпретатор не видит пакеты окружения. Импорт отказывает.
- Как проверить
-
Посмотрите команду запуска и наличие пакета в обоих интерпретаторах.
systemctl show myapp.service -p ExecStart /opt/myapp/venv/bin/python -c "import flask" 2>&1 | tail -1
- Как исправить
-
Укажите в команде запуска интерпретатор из окружения по полному пути. Активация окружения в unit-файле не нужна и не работает.
[Service] ExecStart=/opt/myapp/venv/bin/python -m myapp
- Почему происходит
- После обновления системного интерпретатора окружение может перестать работать: ссылки внутри указывают на исчезнувшую версию.
- Как проверить
-
Посмотрите, куда ведёт интерпретатор окружения.
ls -l /opt/myapp/venv/bin/python*; /opt/myapp/venv/bin/python -V 2>&1
- Как исправить
- Пересоздайте окружение под текущую версию интерпретатора и установите зависимости заново. Починить ссылки на месте обычно не удаётся.
- Почему происходит
- Параметры защиты системы делают каталог недоступным, и запуск отказывает с кодом исполнения.
- Как проверить
-
Посмотрите параметры изоляции и доступность пути.
systemctl show myapp.service -p ProtectSystem -p ProtectHome -p ReadOnlyPaths sudo -u myapp test -x /opt/myapp/venv/bin/python && echo доступен || echo недоступен
- Как исправить
- Разрешите нужный путь в параметрах изоляции. Окружение в домашнем каталоге пользователя особенно часто попадает под защиту домашних каталогов.
Пример вывода
В unit-файле указан системный интерпретатор. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
systemd[1]: Started myapp.service - My application.
python3[12500]: Traceback (most recent call last):
python3[12500]: File "/opt/myapp/app.py", line 1, in <module>
python3[12500]: ModuleNotFoundError: No module named 'flask'
systemd[1]: myapp.service: Main process exited, code=exited, status=1/FAILURE
Связанные ошибки
- Python-служба: ModuleNotFoundError при запуске Служба не находит модули: другое виртуальное окружение, неверный интерпретатор, отсутствующие зависимости.
- status=203/EXEC в systemd Код 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
- Node-служба не видит переменные окружения Приложение падает из-за отсутствующих переменных: файл .env не читается службой, окружение задаётся иначе.
- Celery: обработчик работает, но задачи не берутся Служба обработчика активна, очередь растёт: не та очередь, недоступный брокер, префикс имён.
- Gunicorn: WORKER TIMEOUT в журнале службы Рабочие процессы Gunicorn убиваются по таймауту: медленные запросы, блокирующие вызовы, неверный тип обработчика.
- uWSGI: веб-сервер не может писать в сокет nginx получает отказ доступа к сокету uWSGI: права и владелец сокета задаются в описании приложения.
- В терминале работает, а под systemd нет Самая частая жалоба: программа запускается руками, но не как служба. Полный разбор отличий окружения.
- Журнал службы пуст, хотя приложение работает Вывод приложения не появляется в журнале: буферизация вывода при перенаправлении в канал.
Источники
-
systemd.service(5)
ExecStart= и запуск по полному пути. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено unit-файлом с системным интерпретатором при пакетах в окружении.