我正在使用 subprocess.Popen 执行操作系统命令。这是我试图在代码中模拟的内容:
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
。
第一种方法有效,但后一种方法对我来说似乎“更干净”。
为什么 Popen
不允许我在列表中指定参数?
最佳答案
当您使用shell=True
时在 UNIX 上,您应该以字符串形式提供参数。当您提供列表时,subprocess
将列表中的第一项解释为整个命令字符串,并将列表中的其余项目解释为传递给 shell 本身的参数,而不是您的命令。因此,在上面的示例中,您最终会得到如下结果:
/bin/sh -T filer < /dev/myscript -c "/usr/sbin/ssh"
绝对不是你的意思!
相反,当您使用shell=False
时,如果您运行不带参数的单个命令,则只能传递字符串。如果您确实有参数,则必须将命令作为序列传递。您也不能通过 <
使用 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
部分.
关于python - subprocess.Popen 和执行 ssh 命令出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25021347/