python:subprocess.Popen()行为

时间:2012-09-19 13:34:08

标签: python subprocess popen

我正在尝试将rsync与python一起使用。我已经读过,将参数传递给Popen的首选方法是使用数组。

我试过的代码:

p = Popen(["rsync",
        "\"{source}\"".format(source=latestPath),
        "\"{user}@{host}:{dir}\"".format(user=user, host=host, dir=dir)],
        stdout=PIPE, stderr=PIPE)

结果是rsync要求输入密码,即使我已经设置了SSH密钥来进行身份验证。

我认为这是新流程执行环境的问题。我接下来尝试的是:

p = Popen(["rsync", 
   "\"{source}\"".format(source=latestPath),
   "\"{user}@{host}:{dir}\"".format(user=user, host=host, dir=dir)],
   stdout=PIPE, stderr=PIPE, shell=True)

这会导致rsync打印“正确用法”,因此参数会错误地传递给rsync。我不确定这是否应该工作(传递一个shell = True的数组)

如果我像这样删除数组:

p = Popen("rsync \"{source}\" \"{user}@{host}:{dir}\"".format(
        source=latestPath, user=user, host=host, dir=dir),
      stdout=PIPE, stderr=PIPE, shell=True)

程序运行正常。这个脚本真的没关系,但我想知道它有什么区别?为什么其他两个(主要是第一个)不起作用?

是否只需要shell环境,第二个是不正确的?

编辑:变量的内容

latestPath='/home/tomcat/.jenkins/jobs/MC 4thworld/workspace/target/FourthWorld-0.1-SNAPSHOT.jar'
user='mc'
host='192.168.0.32'
dir='/mc/test/plugins/'

3 个答案:

答案 0 :(得分:1)

可能与cwdenv参数有关吗?也许在第一种语法中,它找不到SSH密钥......

答案 1 :(得分:1)

  

我想知道有什么区别?

shell=True时,整个命令被传递给shell。引号是存在的,所以shell可以再次正确地选择命令。特别是,传递

foo "bar baz"

到shell会导致它将命令解析为(Python语法)['foo', 'bar baz'],以便它可以使用参数foo执行bar baz命令。

相比之下,当shell=False时,Python会立即将列表中的参数传递给程序。例如,尝试以下subprocess命令:

>>> import subprocess
>>> subprocess.call(["echo", '"Hello!"'])
"Hello!"
0
>>> subprocess.call('echo "Hello!"', shell=True)
Hello!
0

并注意,在第一个中,引号由echo程序回显给您,而在第二种情况下,shell在执行echo之前将它们剥离。

在您的具体情况下,rsync获取引号,但不知道它应该如何处理它们;毕竟,它本身并不是一个外壳。

答案 2 :(得分:1)

只是一个建议,您可能更容易使用sh而不是子进程:

import sh
sh.rsync(latestPath, user+"@"+host+":"+dir)