systemd execstart python守护进程动态地使用来自环境变量

时间:2018-01-26 15:19:58

标签: python virtualenv systemd

我有Python脚本,可以作为CentOS 7中的systemd守护进程。守护进程由我在virtualenv中创建的python版本执行。我试图调整脚本以便能够在环境变量中设置virtualenv路径,这样我就可以通过改变一个变量的路径并重新启动服务来轻松切换到不同的virtualenv。我已经创建了我的systemd脚本,以便能够初始化守护进程的多个实例,这非常有用。当我尝试使用环境变量指向我的python解析器时,事情就会中断。这是我到目前为止所拥有的。

/etc/systemd/system/pipeline-remove@.service:

[Unit]
Description=pipeline remove tickets worker instances as a service, instance %i
Requires=pipeline-remove.service
Before=pipeline-remove.service
BindsTo=pipeline-remove.service

[Service]
PermissionsStartOnly=true
Type=idle
User=root
ExecStart=/path/to/venv/bin/python /pipeline/python/daemons/remove_tickets.py
Restart=always
TimeoutStartSec=10
RestartSec=10

[Install]
WantedBy=pipeline-remove.service

/etc/systemd/system/pipeline-remove.service(启动所有实例):

[Unit]
Description=manages pipeline remove tickets worker instances as a service, instance

[Service]
Type=oneshot
ExecStart=/usr/bin/sh /usr/bin/pipeline-remove-start.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

pipeline-remove-start.sh:

#!/bin/bash
systemctl start pipeline-remove@{1..2}

这对我很有用,但是当我尝试以下列方式设置python dir时,事情就会破坏:

/etc/profile.d/pipeline_envvars.sh:

PIPELINE_VIRTUALENV=/path/to/venv

/etc/systemd/system/pipeline-remove@.service:

[Unit]
Description=pipeline remove tickets worker instances as a service, instance %i
Requires=pipeline-remove.service
Before=pipeline-remove.service
BindsTo=pipeline-remove.service

[Service]
PermissionsStartOnly=true
Type=idle
User=root
EnvironmentFile=/etc/profile.d/pipeline_envvars.sh
ExecStart=/${PIPELINE_VIRTUALENV}/bin/python /pipeline/python/daemons/remove_tickets.py
Restart=always
TimeoutStartSec=10
RestartSec=10

[Install]
WantedBy=pipeline-remove.service

然后我尝试启动它:

sudo systemctl daemon-reload
sudo systemctl restart pipeline-remove@{1..1}
sudo systemctl status pipeline-remove@{1..1}

状态显示以下退出代码203,表示未找到可执行文件:

● pipeline-remove@1.service - pipeline remove tickets worker instances as a service, instance 1
   Loaded: loaded (/etc/systemd/system/pipeline-remove@.service; disabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: exit-code) since Fri 2018-01-26 15:04:50 UTC; 6s ago
  Process: 11716 ExecStart=/${PIPELINE_VIRTUALENV}/bin/python /pipeline/python/daemons/remove_tickets.py (code=exited, status=203/EXEC)
 Main PID: 11716 (code=exited, status=203/EXEC)

Jan 26 15:04:50 dev systemd[1]: pipeline-remove@1.service: main process exited, code=exited, status=203/EXEC
Jan 26 15:04:50 dev systemd[1]: Unit pipeline-remove@1.service entered failed state.
Jan 26 15:04:50 dev systemd[1]: pipeline-remove@1.service failed.

找到了exec代码here。也可以在syslog,/ var / log / messages中找到它:

Jan 26 15:07:13 dev systemd: Starting pipeline remove tickets worker instances as a service, instance 1...
Jan 26 15:07:13 dev systemd: Failed at step EXEC spawning /${PIPELINE_VIRTUALENV}/bin/python: No such file or directory
Jan 26 15:07:13 dev systemd: pipeline-remove@1.service: main process exited, code=exited, status=203/EXEC
Jan 26 15:07:13 dev systemd: Unit pipeline-remove@1.service entered failed state.
Jan 26 15:07:13 dev systemd: pipeline-remove@1.service failed.
Jan 26 15:07:23 dev systemd: pipeline-remove@1.service holdoff time over, scheduling restart.
Jan 26 15:07:23 dev systemd: Started pipeline remove tickets worker instances as a service, instance 1.

当我尝试删除/中的前导ExecStart时,即使我的env var包含绝对路径,我也会收到相对路径错误:

Failed to start pipeline-remove@1.service: Unit is not loaded properly: 
Invalid argument.
See system logs and 'systemctl status pipeline-remove@1.service' for 
details.

状态显示如下:

vagrant@dev:~$ sudo systemctl status pipeline-remove@{1..1}
● pipeline-remove@1.service - pipeline remove tickets worker instances as a service, instance 1
   Loaded: error (Reason: Invalid argument)
   Active: inactive (dead)

Jan 26 15:11:39 dev systemd[1]: pipeline-remove@1.service failed.
Jan 26 15:11:42 dev systemd[1]: Stopped pipeline remove tickets worker instances as a service, instance 1.
Jan 26 15:11:42 dev systemd[1]: [/etc/systemd/system/pipeline-remove@.service:12] Executable path is not absolute, ignoring: ${PIPELINE_VIRTUALENV}/bin/python /pipel...e_tickets.py
Jan 26 15:11:42 dev systemd[1]: pipeline-remove@1.service lacks both ExecStart= and ExecStop= setting. Refusing.

我使用this指南帮助我开始,但现在我被卡住了。如何在从环境变量设置python可执行文件路径时让我的python守护进程出现?

1 个答案:

答案 0 :(得分:0)

经过多次阅读后,我偶然发现了答案here。问题是ExecStart的第一个参数必须是文字:

  

ExecStart =具有在此时执行的参数的命令   服务开始了。对于每个指定的命令,第一个   参数必须是可执行文件的绝对和文字路径。

继续阅读ExecStart,它说:

  

在扩展时未知其值的变量被视为   空字符串。 注意第一个参数(即程序到   执行)可能不是变量

我最终也遇到了answer这个看似同样问题的绊脚石。最后这是有用的:用shell包装整个东西来运行:

[Unit]
Description=pipeline remove tickets worker instances as a service, instance %i
Requires=pipeline-remove.service
Before=pipeline-remove.service
BindsTo=pipeline-remove.service

[Service]
PermissionsStartOnly=true
Type=idle
User=root
EnvironmentFile=/etc/profile.d/pipeline_envvars.sh
ExecStart=/bin/sh -c '${PIPELINE_VIRTUALENV}/bin/python /pipeline/python/daemons/remove_tickets.py'
Restart=always
TimeoutStartSec=10
RestartSec=10

[Install]
WantedBy=pipeline-remove.service

所以ExecStart=/bin/sh -c '<your command>'节省了一天,我现在可以为我的环境变量指定python解释器路径。请留下答案,希望能节省一些时间。