从 python subprocess.call 调用 rsync [英] calling rsync from python subprocess.call

查看:43
本文介绍了从 python subprocess.call 调用 rsync的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to execute rsync over ssh from a subprocess in a python script to copy images from one server to another. I have a function defined as:

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 运行):

What I'm ultimately trying to do is have Python execute this (which works from a 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/

确实是我的打印语句输出:

And indeed my print statement outputs:

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 脚本中执行时,有两个问题:

But when executed from within this python script, there are two problems:

  1. 如果 len(bookIds) > 1,则/shared/books/下的子目录列表会被 bash 或 rsync 以某种方式误解.错误信息是:
    • rsync:link_stat "/shared/books/{book_482,book_347}" 失败:没有那个文件或目录 (2))

好像 subprocess.call 函数需要转义一些字符之类的,不是吗?

Seems as if the subprocess.call function requires some characters to be escaped or something, no?

推荐答案

解决了我的问题.我的问题是由于我误解了 subprocess.call 函数的执行方式以及 bash 对大括号内的列表的扩展.

Figured out my issues. My problems were the result of my misunderstanding of how the subprocess.call function executes and bash's expansion of lists inside curly braces.

当我在带有花括号的子目录的 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}".

When I was issuing the rsync command in a bash shell with subdirectories in curly braces, bash was really expanding that into multiple arguments which were being passed to rsync (/shared/books/book_1 shared/books/book_2, etc.). When passing the same string with curly braces "/shared/books/{book_1, book_2}" to the subprocess.call function, the expansion wasn't happening, since it wasn't going through bash, so my argument to rsync was really "/shared/books/{book_1, book_2}".

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

Similarly, the single quotes around the file patterns ('*', '*.jpg', etc.) work on the bash command line (only the values inside the single quotes are passed to rsync), but inside subprocess.call, the single quotes are passed to rsync as the file pattern ("'*.jpg'").

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

New (working) code looks like this:

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)

这篇关于从 python subprocess.call 调用 rsync的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆