Как включить виртуальную машину в сервисном блоке systemd?
Я хочу "активировать" virtualenv в файле службы systemd.
Я бы хотел, чтобы у меня не было процесса оболочки между процессом systemd и интерпретатором python.
Мое текущее решение выглядит так:
[Unit]
Description=fooservice
After=syslog.target network.target
[Service]
Type=simple
User=fooservice
WorkingDirectory={{ venv_home }}
ExecStart={{ venv_home }}/fooservice --serve-in-foreground
Restart=on-abort
EnvironmentFile=/etc/sysconfig/fooservice.env
[Install]
WantedBy=multi-user.target
/etc/sysconfig/fooservice.env
PATH={{ venv_home }}/bin:/usr/local/bin:/usr/bin:/bin
PYTHONIOENCODING=utf-8
PYTHONPATH={{ venv_home }}/...
VIRTUAL_ENV={{ venv_home }}
Но у меня проблемы. Я получаю ImportErrors, поскольку некоторые из них в sys.path отсутствуют.
Ответы
Ответ 1
Virtualenv "запекается в интерпретаторе Python в virtualenv". Это означает, что вы можете запускать python
или console_scripts
непосредственно в этом virtualenv и вам не нужно сначала активировать virtualenv или управлять PATH
самостоятельно.
ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground
или же
ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground
и удалите запись EnvironmentFile
.
Чтобы убедиться, что это действительно правильно, вы можете проверить sys.path
, запустив
{{ venv_home }}/bin/python -m site
и сравнивая вывод
python -m site
Ответ 2
Несмотря на то, что путь к библиотекам действительно встроен в интерпретатор python для virtualenv, у меня были проблемы с инструментами python, которые использовали двоичные файлы, установленные в этом virtualenv. Например, мой сервис Apache gunicorn
не будет работать, потому что он не может найти gunicorn
файл gunicorn
. Чтобы обойти это, вот моя инструкция ExecStart
с инструкцией Environment
(которая устанавливает переменную окружения только для службы).
ExecStart={{ virtualenv }}/bin/python {{ virtualenv }}/bin/airflow webserver
Environment="PATH={{ virtualenv }}/bin:{{ ansible_env.PATH }}"
ExecStart
явно использует интерпретатор python для virtualenv. Я также добавляю переменную PATH
, которая добавляет двоичную папку virtualenv перед системной PATH
. Таким образом, я получаю нужные библиотеки Python, а также двоичные файлы.
Обратите внимание, что я использую ansible для создания этого сервиса, поэтому фигурные скобки jinja2.
Ответ 3
Я не использую virtualenv, но pyenv: вот только для того, чтобы использовать реальный путь .pyenv в shebang и убедиться, что он находится в PATH
Ex: pyenv активирует flask-prod для пользователя mortenb, который работает в prod
/home/mortenb/.pyenv/versions/flask-prod/bin/python --version
Python 3.6.2
Затем, чтобы мои скрипты, начинающиеся с systemd *.service, добавляли следующий shebang:
#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3