如何在 Systemd 服务单元中启用 Virtual alenv?

我想要在 Systemd 服务文件中“激活”一个 Virtual alenv。

我希望避免 Systemd 进程和 python 解释器之间存在 shell 进程。

我目前的解决方案是这样的:

[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中的一些条目丢失了,所以我得到了进口错误。

91684 次浏览

Viralenv“被放入 viralenv 中的 Python 解释器中”。这意味着你可以直接在那个 viralenv 中启动 python或者 console_scripts,而不需要先激活 viralenv 或者自己管理 PATH:

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

或者

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

并删除 EnvironmentFile条目。

要验证它的确是正确的,可以通过运行

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

并将输出与

python -m site

我没有使用 viralenv,而是使用 pyenv: 这里只是使用真实的。并确保它在 PATH 中

例如: pyenv 为用户 mortenb 激活烧瓶驱动器,它在驱动器中运行

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

然后,在我的烧瓶脚本中,从 systemd * . service 开始,我添加了以下步骤:

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

虽然库的路径实际上已经嵌入到 viralenv 的 python 解释器中,但是我在使用安装在 viralenv 中的二进制文件的 python 工具时遇到了一些问题。例如,我的 apache airflow 服务无法工作,因为它找不到 gunicorn二进制文件。为了解决这个问题,下面是我的 ExecStart指令和一个 Environment指令(它仅仅为服务设置了一个环境变量)。

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

ExecStart显式地使用 viralenv 的 python 解释器。我还添加了一个 PATH变量,它在系统 PATH之前添加了 viralenv 的二进制文件夹。这样,我就可以得到所需的 Python 库和二进制文件。

注意,我正在使用 anable 构建这个服务,因此使用了 jinja2的花括号。

在我的例子中,我只是尝试添加 Flask 所需的环境变量

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

我正在使用 viralenv,因此 /xx/yy/zz/venv/bin是 viralenv 文件夹的路径。