Como habilitar um virtualenv em uma unidade de serviço systemd?


87

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.


Você pode incluir os erros que está recebendo?
Praveen Yalagandula

@PraveenYalagandula O traceback não contém nenhuma informação útil, uma vez que a Exceção ImportError e todas as linhas acima contêm apenas código personalizado que não importa aqui.
guettli

Respostas:


117

O virtualenv é "embutido no interpretador Python no virtualenv". Isso significa que você pode iniciar pythonou console_scriptsdiretamente naquele virtualenv e não precisa ativar o virtualenv primeiro ou gerenciar PATHvocê 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 EnvironmentFileentrada.

Para verificar se está realmente correto, você pode verificar sys.pathexecutando

{{ venv_home }}/bin/python -m site

e comparando a saída com

python -m site

2
bom ponto Nils. A propósito, fooservice.py não faz sentido estar dentro do diretório venv_home, suponho que seja um erro de digitação na pergunta.
stelios

4
Observe que os comandos de impressão sugeridos não são compatíveis com Python 3. Se você estiver usando pelo menos o python 2.4, você pode, alternativamente, apenas usar: python -m sitepara obter uma saída bem formatada da variável sys.path junto com informações adicionais.
Mark Edington

2
Legal, eu não sabia python -m site. Eu ajustei minha resposta.
Nils Werner

1
@NilsWerner Eu acabei resolvendo isso gerando um shell, nada mais funcionou no Ubuntu 17.10: github.com/umccr/pcgr-deploy/blob/master/ansible/files/… ... por favor, ignore o modelo jinja2 para ansible, ele expande-se corretamente quando implantado.
brainstorm

6
Para aqueles que estão se perguntando se este é ninja2 .... não, as chaves duplas são apenas marcadores de posição que o OP inventou: superuser.com/questions/1209919/…
ankostis

12

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 gunicornbinário. Para contornar isso, aqui está minha ExecStartinstrução, com uma Environmentinstruçã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 }}"

ExecStartusa explicitamente o interpretador python do virtualenv. Também estou adicionando uma PATHvariável, que adiciona a pasta binária do virtualenv antes do sistema PATH. 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.


1

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

0

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.