2013-01-11 27 views
12

Tôi đang cố gắng thực thi rsync trên ssh từ một tiến trình con trong kịch bản lệnh python để sao chép hình ảnh từ máy chủ này sang máy chủ khác. Tôi đã một hàm định nghĩa là:gọi rsync từ python subprocess.call

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, "[email protected]" + host + ":/home/jill/web/public/static/"] 
     print "executing " + ' '.join(args) 
     subprocess.call(args) 

Những gì tôi đang cố gắng để cuối cùng làm là có Python thực hiện điều này (trong đó hoạt động từ một vỏ bash):

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

Và quả thực kết quả đầu ra tuyên bố trên báo của tôi:

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

Nhưng khi thực hiện từ bên trong kịch bản python này, có hai vấn đề:

  1. nếu len (bookIds)> 1, danh sách các thư mục con trong/chia sẻ/sách/bằng cách nào đó bị hiểu nhầm bởi bash hoặc rsync. Các thông báo lỗi là:
    • rsync: link_stat "/ chia sẻ/sách/{book_482, book_347}" thất bại: Không có tập tin hoặc thư mục (2))
  2. nếu len (bookIds) == 1, tất cả file trong thư mục nguồn được rsynced (không chỉ là * .jpg, như là ý định của tôi)

có vẻ như nếu chức năng subprocess.call đòi hỏi một số ký tự để được thoát hoặc một cái gì đó, đúng không?

+0

Ra khỏi tò mò, những gì sẽ xảy ra nếu bạn thiết lập 'shell = TRUE' trong cuộc gọi của bạn? Ví dụ, 'subprocess.call (args, shell = True)' – sberry

Trả lời

17

Đã giải quyết được vấn đề của tôi. Vấn đề của tôi là kết quả của sự hiểu lầm của tôi về cách hàm subprocess.call thực hiện và mở rộng danh sách các bash bên trong các dấu ngoặc nhọn.

Khi tôi đang phát lệnh rsync trong bash shell với thư mục con trong dấu ngoặc nhọn, bash thực sự mở rộng thành nhiều đối số được chuyển đến rsync (/ shared/books/book_1 shared/books/book_2, v.v.). Khi truyền cùng một chuỗi với dấu ngoặc nhọn "/ shared/books/{book_1, book_2}" vào hàm subprocess.call, việc mở rộng không xảy ra, vì nó không phải là thông qua bash, vì vậy đối số của tôi cho rsync thực sự "/ shared/books/{book_1, book_2}".

Tương tự, dấu nháy đơn xung quanh mẫu tệp ('*', '* .jpg', v.v.) hoạt động trên dòng lệnh bash (chỉ các giá trị bên trong dấu nháy đơn được chuyển đến rsync), nhưng bên trong subprocess .call, các dấu nháy đơn được chuyển đến rsync làm mẫu tệp ("'* .jpg'").

mới (làm việc) mã trông như thế này:

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("[email protected]" + host + ":/home/jill/web/public/static/"]) 
     print "executing " + ' '.join(args) 
     subprocess.call(args)