rsync: pass command as list, moving the shlex.split to main; support `rsync -e "rsync-wrapper -C --"` style execution with the rsync command given as arguments
--- a/pvl/backup/rsync.py Fri Mar 02 14:41:19 2012 +0200
+++ b/pvl/backup/rsync.py Fri Mar 02 15:39:50 2012 +0200
@@ -8,7 +8,6 @@
from pvl.backup.mount import mount
from pvl.backup import invoke
-import shlex
import os.path
import logging
@@ -102,11 +101,11 @@
# cleanup
# cleanup
-def parse_command (command, restrict_server=True, restrict_readonly=True) :
+def parse_command (command_parts, restrict_server=True, restrict_readonly=True) :
"""
Parse given rsync server command into bits.
- command - the command-string sent by rsync
+ command_parts - the command-list sent by rsync
restrict_server - restrict to server-mode
restrict_readonly - restrict to read/send-mode
@@ -115,16 +114,13 @@
(cmd, options, source, dest)
"""
- # split
- parts = shlex.split(command)
-
cmd = None
options = []
source = None
dest = None
# parse
- for part in parts :
+ for part in command_parts :
if cmd is None :
cmd = part
--- a/scripts/pvlbackup-rsync-wrapper Fri Mar 02 14:41:19 2012 +0200
+++ b/scripts/pvlbackup-rsync-wrapper Fri Mar 02 15:39:50 2012 +0200
@@ -2,6 +2,9 @@
"""
SSH authorized_keys command="..." wrapper for rsync.
+
+ Testing goes something like:
+ sudo sh -c "PYTHONPATH=. rsync -e './scripts/pvlbackup-rsync-wrapper --debug -C --' -ax testing:lvm:asdf:test test/tmp"
"""
from pvl.backup.rsync import RSyncCommandFormatError
@@ -9,6 +12,7 @@
from pvl.backup import rsync
import optparse
+import shlex
import os
import logging
@@ -22,6 +26,8 @@
Parse command-line arguments.
"""
+# import sys; sys.stderr.write("%s\n" % (argv, ))
+
parser = optparse.OptionParser(
prog = argv[0],
@@ -42,6 +48,9 @@
parser.add_option('-c', '--command', metavar='CMD', default=os.environ.get('SSH_ORIGINAL_COMMAND'),
help="rsync command to execute")
+ parser.add_option('-C', '--given-command', action='store_true', default=False,
+ help="use given command in `rsync -e %prog` format")
+
parser.add_option('-R', '--readonly', action='store_true', default=False,
help="restrict to read/source mode")
@@ -112,19 +121,31 @@
# global options + args
options, args = parse_options(argv)
+ # command required
+ if options.given_command :
+ # from args (as given by `rsync -e pvlbackup-rsync-wrapper`) -> 'pvlbackup-rsync-wrapper <host> (<command> ...)'
+ host = args.pop(0)
+ command_parts = args
+
+ log.debug("using command from args: %r", command_parts)
+
# args
- if args :
+ elif args :
log.error("No arguments are handled")
return 2
- # command required
- if not options.command:
+ elif options.command:
+ # as given
+ command_parts = shlex.split(options.command)
+
+ else :
log.error("SSH_ORIGINAL_COMMAND not given")
return 2
+
+ # run
try :
- # handle it
- return rsync_wrapper(options.command)
+ return rsync_wrapper(command_parts)
except Exception, e:
log.error("Internal error:", exc_info=e)