Python rsync error in reading remote root-level files

Question:

I try to setup a cron job to rsync remote files (contains root-level files) into my local server, if I run the command in shell, it works. But if I run this in Python, I got into strange command not found error:

This works if run it in a shell:

rsync -ave ssh --rsync-path='sudo rsync' --delete [email protected]:/tmp/test2 ./test

But this Python script doesn’t:

#!/usr/bin/python

from subprocess import call
....
for src_dir in backup_list:
    call(["rsync", "-ave", "ssh", "--rsync-path='sudo rsync'", "--delete", src_host+src_dir, dst_dir])

It fails with:

local server:$ backup.py
bash: sudo rsync: command not found
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: remote command not found (code 127) at io.c(226) [Receiver=3.1.0]
...
Asked By: kengcc

||

Answers:

It is most likely a spacing error or something small, the way I debug commands is to make sure to prints out. OS.system is a great alternative thats easier although subprocess is better. I am not around my computer to test it but you can either set your subprocess like that, or use this example. This is assuming your on Linux or Mac.

import os 

cmd = ('rsync -ave --delete root' +str(src_host) + str(src_directory) + '' + str(dst_dir)) #variable you can call anytime
os.system(cmd) # actually performs the command
print x # how to  test and make sure 
Answered By: Anekdotin

Quotes around an argument with spaces like you have in "--rsync-path='sudo rsync'" are needed when the shell splits up a long string into arguments, to avoid treating rsync as a separate argument. In your call(), you’re providing the individual arguments, so that splitting of a string into arguments is not performed. With your code as-is, the quotes end up as part of the argument passed to rsync. Just drop them. Here’s a working example of the list passed to a call() for a very similar rsync invocation:


['rsync',
'-arvz',
'-delete',
'-e',
'ssh',
'--rsync-path=sudo rsync',
'192.168.0.17:/remote/directory/',
'/local/directory/']

Answered By: user1692476

I have been facing the same issue:
This piece of code work for me…
join the command while passing to call or Popen and add shell=True.

from subprocess import call
for src_dir in backup_list:
    call( " ".join(["rsync", "-ave", "ssh", "--rsync-path='sudo rsync'", "--delete", src_host+src_dir, dst_dir]) , shell=True)
Answered By: rohit