我使用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
不允许我在列表中指定参数?
答案 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
部分。