Systemdサービスファイルでvirtualenvを「アクティブ化」したい。
Systemdプロセスとpythonインタープリターの間にシェルプロセスが存在しないようにしたいと思います。
私の現在のソリューションは次のようになります。
[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 }}
しかし、私は問題を抱えています。 sys.pathのいくつかのエンティティが欠落しているため、ImportErrorsが発生します。
Virtualenvは「virtualenvのPythonインタープリターに組み込まれています」。これは、そのvirtualenvでpython
または console_scripts
を直接起動でき、先にvirtualenvをアクティブにしたり、PATH
を自分で管理したりする必要がないことを意味します。
ExecStart={{ venv_home }}/bin/fooservice --serve-in-foreground
または
ExecStart={{ venv_home }}/bin/python {{ venv_home }}/fooservice.py --serve-in-foreground
EnvironmentFile
エントリを削除します。
それが実際に正しいことを確認するには、次を実行してsys.path
を確認します。
{{ venv_home }}/bin/python -m site
出力を比較する
python -m site
ライブラリのパスは実際にvirtualenvのpythonインタープリターに組み込まれていますが、そのvirtualenvにインストールされたバイナリを使用していたpythonツールに問題がありました。たとえば、Apacheエアフローサービスは、gunicorn
バイナリが見つからなかったため機能しません。これを回避するために、ここにExecStart
命令とEnvironment
命令(サービスのみの環境変数を設定する)があります。
ExecStart={{ virtualenv }}/bin/python {{ virtualenv }}/bin/airflow webserver
Environment="PATH={{ virtualenv }}/bin:{{ ansible_env.PATH }}"
ExecStart
explicitlyは、virtualenvのpythonインタープリターを使用します。システムPATH
の前にvirtualenvのバイナリフォルダーを追加するPATH
変数も追加しています。そうすれば、目的のpythonライブラリとバイナリを取得できます。
このサービスを構築するためにansibleを使用していることに注意してください。jinja2の中括弧を忘れないでください。