Use python virtual environment in systemd

经常使用python的朋友应该对虚拟环境virtual environment并不陌生,以virtualenvwrapper 为例,它能很好的管理我们python的版本已经对应的包版本的分割管理。

假设我们新建了一个基于python3的test的虚拟环境(请参照上面的链接搭建相关的环境):

1
2
3
4
mkvirtualenv -p python3 test
workon test
which python
# ${HOME}/.virtualenvs/test/bin/python

所以如果直接在terminal使用的话,可以先进入虚拟环境:

1
2
# method 1
python your_script.py

或者直接调用对应的bin:

1
2
# method 2
${HOME}/.virtualenvs/test/bin/python your_script.py

但是如果your_script.py里面再调用python的bin,method 2就没有办法把虚拟环境的bin指向过去,因此,如果不想进入虚拟环境,而直接使用对应的bin文件的话,我们可以通过修改PATH指向让系统首先搜索到虚拟环境的bin

1
PATH=${HOME}/.virtualenvs/test/bin:$PATH

基于以上原理,我们可以通过结合method2和设置Environment参数在systemd里面启用对应的python虚拟环境,参考配置some.service:

1
2
3
4
5
6
7
8
9
10
11
12
13
# some.service
[Unit]
Description=test
After=auditd.service systemd-user-sessions.service time-sync.target
[Service]
Environment=PATH=${HOME}/.virtualenvs/test/bin/:$PATH
ExecStart=${HOME}/.virtualenvs/test/bin/python your_script.py
ExecReload=/bin/kill $MAINPID
KillMode=process
[Install]
WantedBy=multi-user.target


2016/10/19 update

如果通过上面启动的服务需要调用subprocess的话,可能会发生找不到相关PATH下的binary, 这里提供另外一个解决思路:

首先建立一个shell script

1
2
3
#!/usr/bin/sh
source ${HOME}/.virtualenvs/test/bin/activate
python your_script.py

然后修改service指向到该script

1
2
3
4
5
6
7
8
9
10
11
12
# some.service
[Unit]
Description=test
After=auditd.service systemd-user-sessions.service time-sync.target
[Service]
ExecStart=${absolute_path_to_shell_script}
ExecReload=/bin/kill $MAINPID
KillMode=process
[Install]
WantedBy=multi-user.target

然后正常重启service就可以

: 以上可根据需要替换${HOME}

Zhanzhao Deo Liang wechat
欢迎关注我的个人订阅号: deoXdeo
今天的午餐全赖有你支持!