Я хочу «активировать» виртуальный сервер в служебном файле 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 отсутствуют.

Ответы (4)

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

В моем случае я просто попытался добавить переменные среды, необходимые для Flask, например

[Service]
Environment="PATH=/xx/yy/zz/venv/bin"
Environment="FLASK_ENV=development"
Environment="APP_SETTINGS=config.DevelopmentConfig"

Я использовал virtualenv, поэтому / xx / yy / zz / venv / bin - это путь к папке virtualenv.

Я использую не virtualenv, а pyenv: здесь просто нужно использовать реальный путь .pyenv в shebang и убедиться, что он находится в PATH

Пример: pyenv активирует flask-prod для пользователя mortenb, который работает в prod

/home/mortenb/.pyenv/versions/flask-prod/bin/python --version
Python 3.6.2

Затем к моим скриптам фляги, запускаемым в systemd * .service, я добавляю следующий шебанг:

#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3

Хотя путь к библиотекам действительно запечен в интерпретаторе python virtualenv, у меня были проблемы с инструментами python, которые использовали двоичные файлы, установленные в этом virtualenv. Например, моя служба воздушного потока apache не будет работать, потому что она не может найти двоичный файл 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.

2022 WebDevInsider