Wie aktiviere ich eine virtuelle Umgebung in einer systemd Service Unit?

85

Ich möchte eine virtuelle Umgebung in einer systemd-Dienstdatei "aktivieren".

Ich möchte vermeiden, einen Shell-Prozess zwischen dem systemd-Prozess und dem Python-Interpreter zu haben.

Meine aktuelle Lösung sieht folgendermaßen aus:

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

Aber ich habe Probleme. Ich erhalte ImportErrors, da einige Enties in sys.path fehlen.

guettli
quelle
Können Sie bitte die Fehler angeben, die Sie erhalten?
Praveen Yalagandula
@PraveenYalagandula Der Traceback enthält keine nützlichen Informationen, da die ImportError-Ausnahme und alle Zeilen darüber nur benutzerdefinierten Code enthalten, der hier keine Rolle spielt.
Guettli

Antworten:

112

Die virtuelle Umgebung wird "in die Python-Interpretation in der virtuellen Umgebung eingebrannt". Dies bedeutet, dass Sie diese virtuelle Umgebung starten pythonoder console_scriptsdirekt in dieser virtuellen Umgebung starten können und die virtuelle Umgebung nicht zuerst aktivieren oder PATHselbst verwalten müssen :

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

oder

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

und entfernen Sie den EnvironmentFileEintrag.

Um zu überprüfen, ob es tatsächlich korrekt ist, können Sie dies sys.pathdurch Ausführen überprüfen

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

und Vergleichen der Ausgabe mit

python -m site
Nils Werner
quelle
2
guter Punkt Nils. Übrigens macht fooservice.py keinen Sinn, sich im Verzeichnis venv_home zu befinden. Ich nehme an, es ist ein Tippfehler in der Frage.
Stelios
4
Beachten Sie, dass die vorgeschlagenen Druckbefehle nicht mit Python 3 kompatibel sind. Wenn Sie mindestens Python 2.4 verwenden, können Sie alternativ einfach python -m siteFolgendes verwenden , um eine gut formatierte Ausgabe der Variablen sys.path zusammen mit zusätzlichen Informationen zu erhalten.
Mark Edington
2
Ordentlich, ich wusste nichts davon python -m site. Ich habe meine Antwort angepasst.
Nils Werner
1
@NilsWerner Am Ende habe ich es gelöst, indem ich eine Shell erzeugt habe. Unter Ubuntu 17.10 hat nichts anderes funktioniert: github.com/umccr/pcgr-deploy/blob/master/ansible/files/… ... bitte ignoriere die jinja2-Vorlage für ansible, it Wird bei der Bereitstellung korrekt erweitert.
Brainstorming
6
Für diejenigen fragen , ob dies ninja2 ist .... nein, die doppelt geschweiften Klammern sind nur Platzhalter der OP erfunden: superuser.com/questions/1209919/...
ankostis
11

Während der Pfad für Bibliotheken tatsächlich in den Python-Interpreter der virtuellen Umgebung eingebettet ist, hatte ich Probleme mit Python-Tools, die in dieser virtuellen Umgebung installierte Binärdateien verwendeten. Zum Beispiel würde mein Apache-Luftstromdienst nicht funktionieren, weil er die gunicornBinärdatei nicht finden konnte . Um dies zu umgehen, ist hier meine ExecStartAnweisung mit einer EnvironmentAnweisung (die eine Umgebungsvariable nur für den Dienst festlegt).

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

ExecStartVerwendet explizit den Python-Interpreter der virtuellen Umgebung. Ich PATHfüge auch eine Variable hinzu, die den Binärordner der virtuellen Umgebung vor dem System hinzufügt PATH. Auf diese Weise erhalte ich die gewünschten Python-Bibliotheken sowie Binärdateien.

Beachten Sie, dass ich ansible verwende, um diesen Service zu erstellen, also die geschweiften Klammern von jinja2.

Alexis Lessard
quelle
1

Ich verwende nicht virtualenv, sondern pyenv: Hier ist es nur, um den realen .pyenv-Pfad im Shebang zu verwenden und sicherzustellen, dass er im PATH ist

Beispiel: pyenv aktiviert flask-prod für den Benutzer mortenb, der in prod ausgeführt wird

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

Dann füge ich meinen Kolbenskripten, die in systemd * .service beginnen, den folgenden Shebang hinzu:

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

In meinem Fall habe ich nur versucht, beispielsweise Umgebungsvariablen hinzuzufügen, die für Flask erforderlich sind

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

Ich habe virtualenv verwendet, also /xx/yy/zz/venv/binist der Pfad des virtualenv-Ordners.

Sebastian Cardona Osorio
quelle