【问题标题】:python subprocess fails to find shell commands when started by systemctlpython子进程在systemctl启动时找不到shell命令
【发布时间】:2019-05-19 10:06:38
【问题描述】:

当我使用 systemctl 启动 python 应用程序时,python 子进程在运行标准 shell 命令(如 tail、awk 等)时失败。

代码示例:

import subprocess

process = subprocess.Popen(['awk'], stdout=subprocess.PIPE)

保存以上内容并通过 python app.py 运行它 - 没问题。

使用 systemctl 运行相同的命令,您将收到以下错误:

FileNotFoundError: [Errno 2] No such file or directory: 'awk': 'awk'

对于我已经安装的所有其他命令,如tail、sed 等,也是如此。

我尝试了不同的方式来启动子进程,例如subprocess.run()subprocess.call()。我也尝试使用shell=True 甚至executable='/bin/bash 参数。

对于 systemctl 方面,我尝试使用 systemctl start service_name --user 和各种配置组合在本地运行 - 例如更改进程类型、以 root 身份运行、不同的用户和组。

这是一个配置示例:

[Unit]
Description={{ project_name }} Service
After=network.target

[Service]
User={{ user }}
Group={{ user_group }}

Restart=always
RestartSec=1s

WorkingDirectory=/home/{{ user }}/{{ project_folder }}
ExecStart=/home/{{ user }}/{{ project_folder }}/virtualenv/bin/python start.py

[Install]
WantedBy=multi-user.target

【问题讨论】:

  • tail 已经可以执行;你为什么要使用bash
  • 请提供您有问题的systemd服务内容
  • tail 在使用 systemd 运行时在子进程中不可执行,这就是我尝试这样做的原因。
  • 我会尽快添加 systemd 服务,但它很标准。
  • 您是否尝试过使用tail的完整路径?

标签: python bash subprocess systemd systemctl


【解决方案1】:

事实证明,python 子进程正在使用 PATH 环境变量来定位可执行文件。

运行 systemctl 时,不提供这些。

我通过比较 print(os.environ) 在使用 systemctl 和使用 python app.py 运行时发现了这一点。

在 systemctl 配置文件的 [Service] 部分添加这一行:

Environment="PATH=/home/{{ user }}/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"

【讨论】:

  • 这就是 everything 用来查找可执行文件的方法。
  • 您还应该包括/bin
  • @tripleee 是的,我知道。我非常惊讶地发现 systemctl 不提供这些。
【解决方案2】:
[Unit]
Description={{ project_name }} Service
After=network.target

[Service]
User={{ user }}
Group={{ user_group }}

Restart=always
RestartSec=1s

Environment="PATH=/usr/bin"
WorkingDirectory=/home/{{ user }}/{{ project_folder }}
ExecStart=/home/{{ user }}/{{ project_folder }}/virtualenv/bin/python start.py

[Install]
WantedBy=multi-user.target

这指定程序执行awk命令的环境目录。

在ubuntu 20.04 LTS中,修改代码如下:

import subprocess

process = subprocess.Popen(['/usr/bin/awk'], stdout=subprocess.PIPE)

【讨论】:

    猜你喜欢
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-09
    相关资源
    最近更新 更多