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. Recibo ImportErrors ya que faltan algunas entradas en sys.path.
python
environment-variables
virtualenv
guettli
fuente
fuente
Respuestas:
El virtualenv está "integrado en el intérprete de Python en el virtualenv". Esto significa que puede iniciar
python
oconsole_scripts
directamente en ese virtualenv y no necesita activar primero el virtualenv o administrarsePATH
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
EnvironmentFile
entrada.Para verificar que sea correcto, puede verificar
sys.path
ejecutandoy comparando la salida con
fuente
python -m site
para obtener una salida con un formato agradable de la variable sys.path junto con información adicional.python -m site
. He ajustado mi respuesta.Si bien la ruta de las bibliotecas está integrada en el intérprete de Python del virtualenv, he tenido problemas con las herramientas de Python que usaban binarios instalados en ese virtualenv. Por ejemplo, mi servicio de flujo de aire apache no funcionaría porque no pudo encontrar el
gunicorn
binario. Para solucionar esto, aquí está miExecStart
instrucción, con unaEnvironment
instrucción (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
utiliza explícitamente el intérprete de Python del virtualenv. También estoy agregando unaPATH
variable, que agrega la carpeta binaria del virtualenv antes del sistemaPATH
. De esa manera, obtengo las bibliotecas de Python deseadas, así como los binarios.Tenga en cuenta que estoy usando ansible para construir este servicio, ergo las llaves de jinja2.
fuente
No estoy usando virtualenv sino pyenv: aquí está solo para usar la ruta .pyenv real en el shebang y asegurarse de que esté en la RUTA
Ejemplo: pyenv activa 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 matraces que comienzan en systemd * .service, agrego el siguiente shebang:
#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3
fuente
En mi caso, solo intenté agregar variables de entorno requeridas para Flask, por ejemplo
[Service] Environment="PATH=/xx/yy/zz/venv/bin" Environment="FLASK_ENV=development" Environment="APP_SETTINGS=config.DevelopmentConfig"
Estaba usando virtualenv, así que
/xx/yy/zz/venv/bin
es la ruta de la carpeta virtualenv.fuente