1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
#!/usr/bin/env python
# -*- Mode: python -*-
# Copyright (c) 2009, Andrew McNabb
# Copyright (c) 2003-2008, Brent N. Chun
"""Parallel rsync to the set of nodes in hosts.txt.
For each node, we essentially do a rsync -rv -e ssh local user@host:remote.
Note that remote must be an absolute path.
"""
import os
import re
import sys
parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
if os.path.exists(os.path.join(parent, 'psshlib')):
sys.path.insert(0, parent)
from psshlib import psshutil
from psshlib.task import Task
from psshlib.manager import Manager
from psshlib.cli import common_parser, common_defaults
def option_parser():
parser = common_parser()
parser.usage = "%prog [OPTIONS] -h hosts.txt local remote"
parser.epilog = ("Example: prsync -r -h hosts.txt -l irb2 foo " +
"/home/irb2/foo")
parser.add_option('-r', '--recursive', dest='recursive',
action='store_true', help='recusively copy directories (OPTIONAL)')
parser.add_option('-a', '--archive', dest='archive', action='store_true',
help='use rsync -a (archive mode) (OPTIONAL)')
parser.add_option('-z', '--compress', dest='compress', action='store_true',
help='use rsync compression (OPTIONAL)')
parser.add_option('-S', '--ssh-args', metavar="ARGS", dest='ssh_args',
action='store', help='extra arguments for ssh')
return parser
def parse_args():
parser = option_parser()
defaults = common_defaults()
parser.set_defaults(**defaults)
opts, args = parser.parse_args()
if len(args) < 1:
parser.error('Paths not specified.')
if len(args) < 2:
parser.error('Remote path not specified.')
if len(args) > 2:
parser.error('Extra arguments given after the remote path.')
if not opts.host_files and not opts.host_entries:
parser.error('Hosts not specified.')
return opts, args
def do_prsync(hosts, local, remote, opts):
if opts.outdir and not os.path.exists(opts.outdir):
os.makedirs(opts.outdir)
if opts.errdir and not os.path.exists(opts.errdir):
os.makedirs(opts.errdir)
manager = Manager(opts)
for host, port, user in hosts:
ssh = ['ssh']
if opts.options:
ssh += ['-o', opts.options]
if port:
ssh += ['-p', port]
if opts.ssh_args:
ssh += opts.ssh_args
cmd = ['rsync', '-e', ' '.join(ssh)]
if opts.verbose:
cmd.append('-v')
if opts.recursive:
cmd.append('-r')
if opts.archive:
cmd.append('-a')
if opts.compress:
cmd.append('-z')
if opts.extra:
cmd.extend(opts.extra)
cmd.append(local)
if user:
cmd.append('%s@%s:%s' % (user, host, remote))
else:
cmd.append('%s:%s' % (host, remote))
t = Task(host, port, user, cmd, opts)
manager.add_task(t)
manager.run()
if __name__ == "__main__":
opts, args = parse_args()
local = args[0]
remote = args[1]
if not re.match("^/", remote):
print("Remote path %s must be an absolute path" % remote)
sys.exit(3)
hosts = psshutil.read_hosts(opts.host_files, default_user=opts.user)
if opts.host_entries:
for entry in opts.host_entries:
hosts.append(psshutil.parse_host(entry, default_user=opts.user))
do_prsync(hosts, local, remote, opts)
|