【问题标题】:Why do I need shell=True here in order for Python's subprocess.check_output to work?为什么我在这里需要 shell=True 才能使 Python 的 subprocess.check_output 工作?
【发布时间】:2016-07-28 09:58:43
【问题描述】:

我有一个 python 脚本,它在建立 PPP 连接时由 Linux 上的 ppp 程序调用的 if-up 脚本运行。 python脚本基本上是调用命令行程序,解析结果并返回:

import subprocess

result = subprocess.check_output(["fw_printenv", "serialnr"])
result = # some operation 
return result

虽然当我从命令行手动运行 python 脚本(例如python script.py)时,这段代码可以 100% 正常工作,但当它由 PPP 从 if-up 运行时,它根本不起作用。调用subprocess.check_output 时会引发异常:[Errno 2] No such file or directory: 'fw_printenv'

只有将代码更改为:

result = subprocess.check_output("fw_printenv serialnr", shell=True)

为什么?

【问题讨论】:

  • 通过使用 shell,您正在使用系统的 PATH 变量。这很可能是第一个版本找不到可执行文件的原因

标签: python shell python-3.x terminal subprocess


【解决方案1】:

来自subprocess documentation

如果 shell 为 True,指定的命令将通过 shell 执行。如果您将 Python 主要用于它在大多数系统 shell 上提供的增强控制流,并且仍然希望方便地访问其他 shell 功能,例如 shell 管道、文件名通配符、环境变量扩展和~ 扩展至用户的主目录。但是,请注意 Python 本身提供了许多类似 shell 的功能的实现(特别是 glob、fnmatch、os.walk()、os.path.expandvars()、os.path.expanduser() 和 shutil)。

环境变量是获取二进制文件路径所必需的(尤其是PATH,包含可能的路径,包括unix系统下的/usr/bin/)。 否则,fw_printenv 可能是 accessed by absolute path

【讨论】:

    【解决方案2】:

    使用绝对路径:

    result = subprocess.check_output(["/full/path/to/fw_printenv", "serialnr"])
    

    通过 cron 和 Web 服务器运行的东西也是如此。

    shell=True 显然会打开一个 shell,但不太明显的是,它还设置了所有环境变量(例如 PATH)——就像您在终端中手动运行脚本一样。删除shell=True 并改用绝对路径可能是最好/最安全的选择,如果它有效(我认为它会)。

    【讨论】:

      猜你喜欢
      • 2019-11-15
      • 2017-08-14
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 2012-07-13
      • 2019-12-23
      • 1970-01-01
      • 2019-05-18
      相关资源
      最近更新 更多