从python subprocess.call调用rsync

时间:2013-01-11 06:01:33

标签: python arguments call subprocess rsync

我正在尝试从python脚本中的子进程通过ssh执行rsync,以将映像从一个服务器复制到另一个服务器。我有一个函数定义为:

def rsyncBookContent(bookIds, serverEnv):
    bookPaths = ""
    if len(bookIds) > 1:
        bookPaths = "{" + ",".join(("book_"+str(x)) for x in bookIds) + "}"
    else:
        bookPaths = "book_" + str(bookIds[0])

    for host in serverEnv['content.hosts']:
        args = ["rsync", "-avz", "--include='*/'", "--include='*.jpg'", "--exclude='*'", "-e", "ssh", options.bookDestDir + "/" + bookPaths, "jill@" + host + ":/home/jill/web/public/static/"]
        print "executing " + ' '.join(args)
        subprocess.call(args)

我最终要做的是让Python执行这个(从bash shell开始):

rsync -avz --include='*/' --include='*.jpg' --exclude='*' -e ssh /shared/books/{book_482,book_347} jill@10.12.27.20:/home/jill/web/public/static/

确实我的印刷语句输出:

executing rsync -avz --include='*/' --include='*.jpg' --exclude='*' -e ssh /shared/books/{book_482,book_347} jill@10.12.27.20:/home/jill/web/public/static/

但是当从这个python脚本中执行时,有两个问题:

  1. if len(bookIds)> 1,/ shared / books /下的子目录列表被bash或rsync错误解释。错误消息是:
    • rsync:link_stat“/ shared / books / {book_482,book_347}”失败:没有此类文件或目录(2))
  2. 如果len(bookIds)== 1,源目录下的所有文件都是rsynced(不仅仅是* .jpg,我的意图)
  3. 好像subprocess.call函数需要转义一些字符或其他东西,没有?

1 个答案:

答案 0 :(得分:18)

弄清楚我的问题。我的问题是我误解了subprocess.call函数如何执行以及bash扩展大括号内的列表的结果。

当我在bash shell中发布带有大括号子目录的rsync命令时,bash真的将它扩展为多个参数,这些参数被传递给rsync(/ shared / books / book_1 shared / books / book_2等) 。将带有大括号“/ shared / books / {book_1,book_2}”的相同字符串传递给subprocess.call函数时,扩展没有发生,因为它没有经过bash,所以我对rsync的论证确实是“/ shared / books / {book_1,book_2}”。

类似地,文件模式('*','* .jpg'等)周围的单引号在bash命令行上工作(只有单引号内的值传递给rsync),但在子进程内。调用时,单引号作为文件模式(“'* .jpg'”)传递给rsync。

新的(工作)代码如下所示:

def rsyncBookContent(bookIds, serverEnv):
    bookPaths = []
    for b in bookIds:
        bookPaths.append(options.bookDestDir + "/book_" + str(b))
    args = []
    for host in serverEnv['content.hosts']:
        # copy all *.jpg files via ssh
        args = ["rsync", "-avz", "--include", "*/", "--include", "*.jpg", "--exclude", "*", "-e", "ssh"]
        args.extend(bookPaths)
        args.append("jill@" + host + ":/home/jill/web/public/static/"])
        print "executing " + ' '.join(args)
        subprocess.call(args)