Copying a File to Another Machine

Table of contents:

Problem

You want to programatically send files to another computer, the way the Unix scp command does.

Solution

Use the Net:SSH library to get a secure shell connection to the other machine. Start a cat process on the other machine, and write the file you want to copy to its standard input.

	require 
ubygems
	require 
et/ssh

	def copy_file(session, source_path, destination_path=nil)
	 destination_path ||= source_path
	 cmd = %{cat > "#{destination_path.gsub(", \")}"}
	 session.process.popen3(cmd) do |i, o, e|
	 puts " 
Copying #{source_path} to #{destination_path}… "
	 open(source_path) { |f| i.write(f.read) }
	 puts Done.
	 end
	end

	Net::SSH.start(example.com, :username=>leonardr,
	 :password=>mypass) do |session|
	 copy_file(session, /home/leonardr/scripts/test.rb)
	 copy_file(session, /home/leonardr/scripts/"test".rb)
	end
	# Copying /home/leonardr/scripts/test.rb to /home/leonardr/scripts/test.rb…
	# Done.
	# Copying /home/leonardr/scripts/"test".rb to /home/leonardr/scripts/"test".rb…
	# Done.

Discussion

The scp command basically implements the old rcp protocol over a secured connection. This code uses a shortcut to achieve the same result: it uses the high-level SSH interface to spawn a process on the remote host which writes data to a file.

Since you can run multiple processes at once over your SSH session, you can copy multiple files simultaneously. For every file you want to copy, you need to spawn a cat process:

	def do_copy(session, source_path, destination_path=nil)
	 destination_path ||= source_path
	 cmd = %{cat > "#{destination_path.gsub(", \")}"}
	 cat_process = session.process.open(cmd)

	 cat_process.on_success do |p|
	 p.write(open(source_path) { |f| f.read })
	 p.close
	 puts "Copied #{source_path} to #{destination_path}."
	 end
	end

The call to session.process.open creates a process-like object that runs a cat command on the remote system. The call to on_success registers a callback code block with the process. That code block will run once the cat command has been set up and is accepting standard input. Once that happens, its safe to start writing data to the file on the remote system.

Once youve set up all your copy operations, you should call session.loop to perform all the copy operations simultaneously. The processes won actually be initialized until you call session.loop.

	Net::SSH.start(example.com, :username=>leonardr,
	 :password=>mypass) do |session|
	 do_copy(session, /home/leonardr/scripts/test.rb)
	 do_copy(session, /home/leonardr/new_index.html,
	 /home/leonardr/public_html/index.html)
	 session.loop
	end
	# Copied /home/leonardr/scripts/test.rb to /home/leonardr/scripts/test.rb
	# Copied /home/leonardr/new_index.html to /home/leonardr/public_html/index.html



Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net