python - new - ¿Cómo habilitar un virtualenv en una unidad de servicio systemd?
virtualenv new env (3)
Quiero "activar" un virtualenv en un archivo de servicio systemd.
Me gustaría evitar tener un proceso de shell entre el proceso systemd y el intérprete de python.
Mi solución actual se ve así:
[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 }}
Pero estoy teniendo problemas. Obtengo ImportErrors porque faltan algunas entradas en sys.path.
El virtualenv está "integrado en el intérprete de Python en el virtualenv".
Esto significa que puede iniciar
python
o
console_scripts
directamente en ese virtualenv y no necesita activar el virtualenv primero o administrar
PATH
usted mismo .:
ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground
o
ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground
y elimine la entrada
EnvironmentFile
.
Para verificar que es correcto, puede verificar
sys.path
ejecutando
{{ venv_home }}/bin/python -m site
y comparando la salida a
python -m site
No estoy usando virtualenv sino pyenv: aquí es solo para usar la ruta real .pyenv en shebang y asegurarme de que esté en la RUTA
Ej: pyenv active flask-prod para el usuario mortenb que se ejecuta en prod
/home/mortenb/.pyenv/versions/flask-prod/bin/python --version
Python 3.6.2
Luego, a mis scripts de matraz que comienzan en systemd * .service, agrego el siguiente shebang:
#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3
Si bien el camino para las bibliotecas está realmente integrado en el intérprete de Python del virtualenv, he tenido problemas con las herramientas de Python que estaban utilizando binarios instalados en ese virtualenv.
Por ejemplo, mi servicio de flujo de aire apache no funcionaría porque no pudo encontrar el binario
gunicorn
.
Para evitar esto, aquí está mi instrucción
ExecStart
, con una instrucción de
Environment
(que establece una variable de entorno solo para el servicio).
ExecStart={{ virtualenv }}/bin/python {{ virtualenv }}/bin/airflow webserver
Environment="PATH={{ virtualenv }}/bin:{{ ansible_env.PATH }}"
ExecStart
usa explícitamente el intérprete de python de virtualenv.
También estoy agregando una variable
PATH
, que agrega la carpeta binaria de virtualenv antes del sistema
PATH
.
De esa manera, obtengo las bibliotecas python deseadas, así como los binarios.
Tenga en cuenta que estoy usando ansible para construir este servicio, ergo las llaves de jinja2.