2013-01-11 15 views
12

Próbuję wykonać rsync przez ssh z podprocesu w skrypcie Pythona, aby skopiować obrazy z jednego serwera na drugi. Mam funkcja zdefiniowana jako:Wywołanie rsync z Pythona 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) 

Co ja ostatecznie próbuje zrobić, to mieć Python wykonać ten (który współpracuje z powłoki bash):

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

i rzeczywiście moje wyjścia instrukcji print:

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

Ale gdy wykonywane od wewnątrz skryptu python, istnieją dwa problemy:

  1. Jeśli len (bookIds)> 1, lista podkatalogów pod/shared/books/jest w jakiś sposób błędnie zinterpretowana przez bash lub rsync. Komunikat o błędzie jest:
    • rsync: link_stat "/ Shared/książki/{book_482, book_347}" nie powiodło się: Nie ma takiego pliku lub katalogu (2))
  2. If Len (bookIds) == 1, wszystkie pliki z katalogu źródłowego są rsynced (nie tylko * .jpg, ponieważ jest moim zamiarem)

Wydaje się, że funkcja subprocess.call wymaga niektóre znaki mają być uciekł albo coś, nie?

+0

z ciekawości, co się dzieje, jeśli ustawisz 'shell = TRUE w zaproszeniu? Na przykład 'subprocess.call (args, shell = True)' – sberry

Odpowiedz

17

Wyliczyłem moje problemy. Moje problemy wynikały z mojego niezrozumienia, w jaki sposób wykonywana jest funkcja podprocesu. I rozwijania list wewnątrz nawiasów klamrowych.

Kiedy wydałem komendę rsync w powłoce bash z podkatalogami w nawiasach klamrowych, bash naprawdę rozszerzył to na wiele argumentów, które były przekazywane do rsync (/ shared/books/book_1 shared/books/book_2, itp.). Podczas przekazywania tego samego ciągu za pomocą nawiasów klamrowych "/ shared/books/{book_1, book_2}" do funkcji subprocess.call, rozszerzenie nie działo się, ponieważ nie przechodziło ono przez bash, więc mój argument do rsync był naprawdę "/ shared/books/{book_1, book_2}".

Podobnie pojedyncze cudzysłowy wokół wzorów plików ("*", "* .jpg" itd.) Działają w linii poleceń basha (tylko wartości wewnątrz pojedynczego cudzysłowu są przekazywane do rsync), ale wewnątrz podprocesu .call, pojedyncze cytaty są przekazywane do rsync jako wzorzec pliku ("'* .jpg" ").

Nowy (pracy) Kod wygląda następująco:

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) 
Powiązane problemy