【问题标题】:Output shell command in python在python中输出shell命令
【发布时间】:2016-04-21 16:53:58
【问题描述】:
def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT)
    return p.communicate()

运行中:

   command = ("git clone " + repo).split()
    run_command(commmnd)

一切正常。但是当我尝试运行多个命令时出现错误。

command = ("git clone www.myrepo.com/etc:etc && cd etc && git stash && git pull).split()
run_command(command)

【问题讨论】:

  • 问题是什么?怎么了?你期望会发生什么?会发生什么?
  • 我想在一行中运行多个命令并将输出存储到一个变量中。我不明白为什么这么多反对意见?我知道这是一个类似于输出 shell 命令的问题。但我需要运行多个命令并输出到变量中,以便稍后将输出显示到 django 应用程序中。好吗?

标签: python shell subprocess


【解决方案1】:

subprocess.check_output()shell=True 选项一起使用,但如果它适用于您,请注意不受信任输入的安全警告。

import subprocess

command = 'git clone www.myrepo.com/etc:etc && cd etc && git stash && git pull'
try:
    output = subprocess.check_output(command, shell=True)
except subprocess.CalledProcessError as exc:
    print("subprocess failed with return code {}".format(exc.returncode))
    print("message: {}".format(exc.message))

在此之后output 包含已执行进程的组合标准输出,如果它成功的话。否则需要处理CalledProcessError 异常。

或者,如果您不能保证命令字符串是安全的,您可以依次执行每个命令,仅当当前命令的返回码为 0 即 CalledProcessError 未引发时才进行下一个命令。

import subprocess
import shlex

command = 'git clone www.myrepo.com/etc:etc && cd etc && git stash && git pull'
output = []
try:
    for cmd in command.split('&&'):
        output.append(subprocess.check_output(shlex.split(cmd)))
except subprocess.CalledProcessError as exc:
    print("{!r} failed with return code {}".format(' '.join(exc.cmd), exc.returncode))
else:
    print(''.join(output))

虽然这在 shell 命令注入方面更安全,但敏感参数仍然可能被其他用户嗅探,例如 ps

【讨论】:

  • 使用 shell=True ,一切正常..但这是一个非常不安全的
  • @RusMine:如果您不使用不受信任的输入来构造command,那么与手动运行类似命令相比,您为什么认为shell=True“非常不安全”?
  • 如果您不控制组成命令的字符串,或者命令行参数在某些方面敏感,例如,这可能是不安全的。包含密钥、密码、信用卡等。否则应该没问题。
  • 非常感谢您的回答 :) 。但是你能告诉我 subprocess.Popen 和 subprocess.check_output 之间的区别吗?因为在我的脚本上添加 shell=True ,一切似乎都正常