我相信这应该很简单,但我无法让它正常工作。
这些是我可以在命令行上运行的命令:
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