Ryan Davis wrote: > * Uses ssh with your ssh settings already in place. > * Uses rsync for efficient transfers. Since you're using the external ssh program, you might consider using the -S option in ssh. It lets you pay the setup cost (authentication, tcp connect) once per host, rather than once per ssh or rsync invocation. Makes a big difference with slow networks or many invocations. In rakefiles, it lets you do the following: m = SSHMaster.for "some.host.net" m.rsync [file1, file2], some_dir_on_that_host m.rsync local_dir, remote_dir, "-az" # or other rsync options m.ssh some_cmd Here's the implementation (needs hacking, I'm sure): class SSHMaster def initialize sock, host @sock, @host = sock, host end def ssh cmd, &block sh "ssh", "-S", @sock, @host, cmd, &block end DEFAULT_RSYNC_OPTS = ["-Cavz", "--exclude='*.bck'", "--progress"] # dst may be "host:foo/bar" or just "foo/bar" def rsync src, dst, opts=DEFAULT_RSYNC_OPTS, *optsrest, &block src = [src] unless src.is_a?(Array) src = FileList[*src] opts = [opts] unless opts.is_a?(Array) host_dst = (dst =~ /\A#{@host}:/) ? dst : "#{@host}:#{dst}" sh "rsync", "--rsh=ssh -S #{@sock}", *((opts + optsrest + src + [host_dst]).flatten), &block end SOCKET_NAME = "ssh_master_for_%r@%h:%p" @master = {} def self.for host master = @master[host] unless master sock = File.join(ENV["TMPDIR"], SOCKET_NAME) cmd = "ssh -M -S #{sock} #{host} 'echo hello; read'" master_pipe = IO.popen(cmd, "r+") master_pipe.gets at_exit do master_pipe.close if master_pipe and not master_pipe.closed? end master = @master[host] = new(sock, host) end master rescue StandardError => ex $stderr.puts "Failed to ssh to #{host}: #{ex.message}" false end end -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407