subprocess.Popen和执行ssh命令的问题

时间:2014-07-29 17:22:04

标签: python python-2.7 subprocess

我使用subprocess.Popen来执行OS命令。以下是我在我的代码中试图模仿的内容:

ssh -T myhost < /path/to/some/file

它的工作原理如下:

def runWorkerCode(filer, filename):
    command = "/usr/bin/ssh -T " + filer + " < /devel/myscript"
    try:
        p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
        out, _ = p.communicate()
    except Exception:
        print "Error: %s" % Exception
        sys.exit(1)
    return out.rstrip().split('\n')

但以下对Popen的调用不起作用:

        p = subprocess.Popen(["/usr/bin/ssh", "-T", filer, "<", "/devel/myscript"], stdout=subprocess.PIPE, shell=True)
        p = subprocess.Popen(["/usr/bin/ssh -T", filer, "< /devel/myscript"], stdout=subprocess.PIPE, shell=True)

我尝试了一些其他组合,但只有我可以开始工作的方法是定义命令变量并仅将其提供给Popen()。我也试过shell=False

第一种方法有效,但后一种方法似乎更清洁&#34;对我来说。

为什么Popen不允许我在列表中指定参数?

1 个答案:

答案 0 :(得分:2)

在UNIX上使用shell=True时,应将参数作为字符串提供。当您提供列表时,subprocess将列表中的第一项解释为整个命令字符串,并将列表中的其余项解释为传递给shell本身的参数,而不是您的命令。因此,在上面的示例中,您最终会得到类似的结果:

/bin/sh -T filer < /dev/myscript -c "/usr/sbin/ssh"

绝对不是你的意思!

相反,当您使用shell=False时,如果您正在运行不带参数的单个命令,则只能传递字符串。如果你有参数,必须将comamnd作为序列传递。您也无法通过<字符使用shell重定向,因为没有涉及shell。

如果您想使用shell=False,可以使用stdin关键字参数将文件句柄传递给/dev/myscript

 f = open("/dev/myscript")
 p = subprocess.Popen(["/usr/bin/ssh", "-T", filer], stdout=subprocess.PIPE, stdin=f, shell=False)

何时传递字符串与何时传递序列的规则非常混乱,尤其是当您将Windows引入混合时。我会仔细阅读documentation以试图理解这一切。查看args部分和shell部分。