如何使用 systemd 在 vi​​rtualenv 中运行命令

如何使用 systemd 在 vi​​rtualenv 中运行命令

我相信这应该很简单,但我无法让它正常工作。

这些是我可以在命令行上运行的命令:

cd /home/debian/ap

# Start a virtualenv
source venv-ap/bin/activate

# This needs to happen inside the virtualenv and takes ~20 seconds
crossbar start

# Outside the virtualenv, perhaps in a different command line window
python3 /home/debian/myscript.py

这些命令必须按此顺序执行。由于 virtualenv、crossbar 的不可执行以及之后的单独 python 脚本,我无法找出让它工作的最佳方法。我目前正在进行的工作:

[Unit]
Description=Start CB
After=network.target

[Service]
Type=simple
User=debian
ExecStartPre=source /home/debian/ap/venv-ap/bin/activate
ExecStart=cd /home/debian/ap/ && crossbar start
Restart=always

[Install]
WantedBy=multi-user.target

答案1

这不起作用,因为source它是一个 shell 命令,所以 systemdExecStart=ExecStartPre=不会直接理解它们......(顺便说一句,cd和 也是如此&&。)

可以通过显式运行 shell 并在那里一起运行所有命令来实现这一点:

ExecStart=/bin/sh -c 'cd /home/debian/ap/ && source venv-ap/bin/activate && crossbar start'

但更好的方法是直接使用 virtualenvpython中的可执行文件,而不是获取“激活”脚本。bin/

如果你看看 virtualenv 的使用文件,你会注意到它说:

ENV/bin被创建,可执行文件所在的位置 - 明显是一个新的Python。因此,运行一个脚本将#! /path/to/ENV/bin/python在该 virtualenv 的 python 下运行该脚本。

换句话说,假设crossbar您要运行的 Python 脚本需要 virtualenv venv-ap,只需crossbar从以下内容开始:

#!/home/debian/ap/venv-ap/bin/python

每当调用时它都会自动使用 virtualenv。

也可以直接从 virtualenv 调用 Python 解释器,方法是:

ExecStart=/home/debian/ap/venv-ap/bin/python /path/to/crossbar start

(另外,对于在特定目录中运行,设置WorkingDirectory=/home/debian/ap比使用cd命令更好。这样你就不需要 shell,systemd 可以为你做更好的错误处理。)

答案2

我想重申@filbranden 的答案第二部分

但更好的方法是直接使用 virtualenv 的 bin/ 中的 python 可执行文件,而不是获取“激活”脚本。

如果你查看 virtualenv 的使用文档,你会注意到它说:

ENV/bin 被创建,可执行文件驻留在其中 - 明显是一个新的 python。因此运行带有 #! 的脚本/path/to/ENV/bin/python 将在此 virtualenv 的 python 下运行该脚本。

不要在未激活 venv 的情况下运行它!公平地说,文档也有误导性。激活 venv 使您能够将工作目录与 python(和 venv-ed 包)路径分开是必须的通常:您不想直接在 venv bin 中运行/放置某些内容,但您安装了一些脚本的依赖项。

考虑以下场景(我敢打赌这是最常见的场景之一):

  • 你需要从 git repo 运行一个脚本,但它的依赖项与你的 python 包不兼容
  • 您创建了一个 virtualenv 并 pip 安装了依赖项
  • 您在某个地方克隆了该存储库,但该脚本并不位于 venv 的 bin 中。

如果您甚至想从 git 存储库处理该应用程序,您希望其文件夹保持原始状态,除了有意义的代码修改。你不会想改变shebang。您可以将整个 venv 放入克隆存储库中的子目录中并 gitignore 它以保持一切井井有条,但是然后:

  • 您可以将 systemd 工作目录设置为克隆的文件夹
  • 您将使用带有子文件夹的 python 完整路径的脚本运行
  • 脚本将找不到 pip-ed deps,因为它们不在工作文件夹中,也不在路径中。如果反转文件夹层次结构(将存储库克隆到 venv 的子文件夹),问题仍然存在。

另外,也许您不想直接运行 python,但是例如:gunicorn,并且您/srv在 venv 位于/var/lib.

不激活 venv 不是一个好习惯,我想知道这个白痴段落是如何进入官方 venv 文档的。是的,某些情况下不需要激活它除了很多现实世界的场景!- 我认为。

ExecStartPre无论如何,都不适用于 venv 的采购,因为它是在与ExecStart命令不同的 shell 中执行的,因此环境变量在后者中不正确。

我建议设置 venv PATHEnvironment

相关内容