Jak włączyć virtualenv w jednostce usługowej systemd?

85

Chcę „aktywować” virtualenv w pliku usługi systemd.

Chciałbym uniknąć procesu powłoki między procesem systemd a interpreterem Pythona.

Moje obecne rozwiązanie wygląda następująco:

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

Ale mam kłopoty. Otrzymuję ImportErrors, ponieważ brakuje niektórych encji w sys.path.

guettli
źródło
Czy możesz dołączyć otrzymywane błędy?
Praveen Yalagandula
@PraveenYalagandula Traceback nie zawiera żadnych przydatnych informacji, ponieważ wyjątek ImportError i wszystkie wiersze powyżej zawierają tylko niestandardowy kod, który nie ma tutaj znaczenia.
guettli

Odpowiedzi:

113

Virtualenv jest „wstawiany do interpretera Pythona w virtualenv”. Oznacza to, że możesz uruchomić pythonlub console_scriptsbezpośrednio w tym virtualenv i nie musisz najpierw aktywować virtualenv ani PATHsamodzielnie zarządzać :

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

lub

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

i usuń EnvironmentFilewpis.

Aby sprawdzić, czy rzeczywiście jest poprawny, możesz sprawdzić sys.path, uruchamiając

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

i porównując dane wyjściowe z

python -m site
Nils Werner
źródło
2
słuszna uwaga Nils. Btw, fooservice.py nie ma sensu znajdować się w katalogu venv_home, przypuszczam, że jest to literówka w pytaniu.
stelios
4
Zauważ, że sugerowane polecenia drukowania nie są kompatybilne z Pythonem 3. Jeśli używasz co najmniej Pythona 2.4, możesz alternatywnie po prostu użyć:, python -m siteaby uzyskać ładnie sformatowane wyjście zmiennej sys.path wraz z dodatkowymi informacjami.
Mark Edington
2
Schludnie, o czym nie wiedziałem python -m site. Dostosowałem odpowiedź.
Nils Werner
1
@NilsWerner Skończyło się na tym, że rozwiązałem to, tworząc powłokę, nic innego nie działało w Ubuntu 17.10: github.com/umccr/pcgr-deploy/blob/master/ansible/files/ ... proszę zignorować szablon jinja2 dla ansible, to rozszerza się poprawnie po wdrożeniu.
burza mózgów
6
Dla tych, którzy zastanawiają się, czy to ninja2… nie, podwójne szelki to tylko symbole zastępcze wymyślone przez OP: superuser.com/questions/1209919/ ...
ankostis
11

Chociaż ścieżka do bibliotek jest rzeczywiście wypalona w interprecie języka Python w virtualenv, miałem problemy z narzędziami Pythona, które korzystały z plików binarnych zainstalowanych w tym virtualenv. Na przykład moja usługa przepływu powietrza Apache nie działałaby, ponieważ nie mogła znaleźć gunicornpliku binarnego. Aby obejść ten problem, oto moja ExecStartinstrukcja z Environmentinstrukcją (która ustawia zmienną środowiskową dla samej usługi).

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

ExecStartjawnie używa interpretera języka Python w virtualenv. Dodam też PATHzmienną, która dodaje folder binarny virtualenv przed systemem PATH. W ten sposób otrzymuję pożądane biblioteki Pythona, a także pliki binarne.

Zauważ, że używam ansible do tworzenia tej usługi, czyli nawiasów klamrowych jinja2.

Alexis Lessard
źródło
1

Nie używam virtualenv, ale pyenv: tutaj wystarczy, aby użyć prawdziwej ścieżki .pyenv w shebang i upewnić się, że jest w PATH

Przykład: pyenv aktywuj kolbę-prod dla użytkownika mortenb, który działa w prod

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

Następnie do moich skryptów flask zaczynających się w systemd * .service dodaję następujący shebang:

#!/home/mortenb/.pyenv/versions/flask-prod/bin/python3
MortenB
źródło
0

W moim przypadku po prostu próbowałem dodać zmienne środowiskowe wymagane na przykład dla Flaska

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

Użyłem virtualenv, więc /xx/yy/zz/venv/binjest to ścieżka do folderu virtualenv.

Sebastian Cardona Osorio
źródło