代码之家  ›  专栏  ›  技术社区  ›  radtek

systemd execstart python守护程序使用virtualenv from环境变量动态启动

  •  0
  • radtek  · 技术社区  · 6 年前

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

    /etc/系统D/系统/管道-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/系统D/系统/管道拆除。服务(启动所有实例):

    [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
    

    管道移除开始。上海:

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

    这对我来说非常有用,但当我尝试按以下方式设置python目录时,情况就不一样了:

    /etc/简介。d/pipeline\U环境变量。上海:

    PIPELINE_VIRTUALENV=/path/to/venv
    

    /etc/系统D/系统/管道-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 回复  |  直到 6 年前
        1
  •  3
  •   radtek    6 年前

    再读了一会儿,我无意中找到了答案 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解释器路径。将保留答案,希望能为其他人节省一些时间。