Come abilitare un virtualenv in un'unità di servizio di systemd?


87

Voglio "attivare" un virtualenv in un file di servizio systemd.

Vorrei evitare di avere un processo di shell tra il processo systemd e l'interprete python.

La mia soluzione attuale è simile a questa:

[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 }}

Ma ho problemi. Ottengo ImportErrors poiché mancano alcuni enti in sys.path.


Puoi includere gli errori che stai ricevendo?
Praveen Yalagandula

@PraveenYalagandula Il traceback non contiene alcuna informazione utile, poiché l'eccezione ImportError e tutte le righe sopra contengono solo codice personalizzato che qui non ha importanza.
guettli

Risposte:


117

Il virtualenv è "integrato nell'interprete Python nel virtualenv". Ciò significa che puoi avviare pythono console_scriptsdirettamente in quel virtualenv e non è necessario attivare prima virtualenv o PATHgestirti:

ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground

o

ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground

e rimuovere la EnvironmentFilevoce.

Per verificare che sia effettivamente corretto puoi controllare sys.patheseguendo

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

e confrontando l'output con

python -m site

2
buon punto Nils. A proposito, fooservice.py non ha senso essere all'interno della directory venv_home, suppongo che sia un errore di battitura nella domanda.
stelios

4
Nota che i comandi di stampa suggeriti non sono compatibili con Python 3. Se stai usando almeno python 2.4, in alternativa puoi semplicemente usare: python -m siteper ottenere un output ben formattato della variabile sys.path insieme a informazioni aggiuntive.
Mark Edington

2
Bello, non lo sapevo python -m site. Ho modificato la mia risposta.
Nils Werner

1
@ NilsWerner Ho finito per risolverlo generando una shell, nient'altro ha funzionato su Ubuntu 17.10: github.com/umccr/pcgr-deploy/blob/master/ansible/files/… ... per favore ignora il templating jinja2 per ansible, it si espande correttamente quando viene distribuito.
brainstorming il

6
Per coloro che si chiedono se questo è ninja2 .... no, le doppie parentesi graffe sono solo segnaposto inventati dall'OP: superuser.com/questions/1209919/…
ankostis

12

Mentre il percorso per le librerie è effettivamente inserito nell'interprete python di virtualenv, ho avuto problemi con gli strumenti python che utilizzavano i binari installati in quel virtualenv. Ad esempio, il mio servizio di flusso d'aria apache non funzionerebbe perché non riusciva a trovare il gunicornbinario. Per ovviare a questo, ecco la mia ExecStartistruzione, con Environmentun'istruzione (che imposta una variabile d'ambiente solo per il servizio).

ExecStart={{ virtualenv }}/bin/python {{ virtualenv }}/bin/airflow webserver
Environment="PATH={{ virtualenv }}/bin:{{ ansible_env.PATH }}"

ExecStartutilizza esplicitamente l'interprete python di virtualenv. Sto anche aggiungendo una PATHvariabile, che aggiunge la cartella binaria di virtualenv prima del sistema PATH. In questo modo, ottengo le librerie Python desiderate oltre ai binari.

Nota che sto usando ansible per creare questo servizio, ergo le parentesi graffe di jinja2.


1

Non sto usando virtualenv ma pyenv: eccolo solo per usare il vero percorso .pyenv nello schema e assicurarmi che sia nel PERCORSO

Es: pyenv attiva flask-prod per l'utente mortenb che è in esecuzione in prod

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

Quindi ai miei script di flask che iniziano in systemd * .service aggiungo il seguente shebang:

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

0

Nel mio caso ho solo provato ad aggiungere le variabili d'ambiente richieste per Flask, ad esempio

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

Stavo usando virtualenv così /xx/yy/zz/venv/binè il percorso della cartella virtualenv.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.