Eu quero "ativar" um virtualenv em um arquivo de serviço systemd.
Eu gostaria de evitar um processo de shell entre o processo systemd e o interpretador python.
Minha solução atual é assim:
[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 }}
Mas estou tendo problemas. Recebo ImportErrors, pois algumas entidades em sys.path estão faltando.
python
environment-variables
virtualenv
Guettli
fonte
fonte
Respostas:
O virtualenv é "embutido no interpretador Python no virtualenv". Isso significa que você pode iniciar
python
ouconsole_scripts
diretamente naquele virtualenv e não precisa ativar o virtualenv primeiro ou gerenciarPATH
você mesmo:ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground
ou
ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground
e remova a
EnvironmentFile
entrada.Para verificar se está realmente correto, você pode verificar
sys.path
executando{{ venv_home }}/bin/python -m site
e comparando a saída com
fonte
python -m site
para obter uma saída bem formatada da variável sys.path junto com informações adicionais.python -m site
. Eu ajustei minha resposta.Embora o caminho para as bibliotecas esteja realmente embutido no interpretador python do virtualenv, tive problemas com ferramentas python que usavam binários instalados nesse virtualenv. Por exemplo, meu serviço de fluxo de ar do Apache não funcionava porque não conseguia encontrar o
gunicorn
binário. Para contornar isso, aqui está minhaExecStart
instrução, com umaEnvironment
instrução (que define uma variável de ambiente apenas para o serviço).ExecStart={{ virtualenv }}/bin/python {{ virtualenv }}/bin/airflow webserver Environment="PATH={{ virtualenv }}/bin:{{ ansible_env.PATH }}"
ExecStart
usa explicitamente o interpretador python do virtualenv. Também estou adicionando umaPATH
variável, que adiciona a pasta binária do virtualenv antes do sistemaPATH
. Dessa forma, obtenho as bibliotecas Python desejadas, bem como os binários.Observe que estou usando ansible para construir este serviço, logo as chaves de jinja2.
fonte
Não estou usando virtualenv, mas pyenv: aqui está apenas para usar o caminho real .pyenv no shebang e certificar-se de que está no PATH
Ex: pyenv ativar flask-prod para o usuário mortenb que está sendo executado no prod
/home/mortenb/.pyenv/versions/flask-prod/bin/python --version Python 3.6.2
Então, aos meus scripts de flask começando em systemd * .service, adiciono o seguinte shebang:
#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3
fonte
No meu caso, apenas tentei adicionar variáveis de ambiente necessárias para o Flask, por exemplo
[Service] Environment="PATH=/xx/yy/zz/venv/bin" Environment="FLASK_ENV=development" Environment="APP_SETTINGS=config.DevelopmentConfig"
Eu estava usando o virtualenv, então
/xx/yy/zz/venv/bin
é o caminho da pasta virtualenv.fonte