Controlling a Process on Another Machine

Problem

You want to run a process on another machine, controlling its input stream remotely, and reading its output and error streams.

Solution

The ruby-ssh gem, first described in Recipe 14.10, provides a popen3 method that works a lot like Rubys built-in popen3, except that the process you spawn runs on another computer.

Heres a method that runs a Unix command on another computer and yields its standard I/O streams to a code block on your computer. All traffic going between the computers is encrypted with SSL. To authenticate yourself against the foreign host, youll either need to provide a username and password, or set up an SSL key pair ahead of time.

	require 
ubygems
	require 
et/ssh

	def run_remotely(command, host, args)
	 Net::SSH.start(host, args) do |session|
	 session.process.popen3(command) do |stdin, stdout, stderr|
	 yield stdin, stdout, stderr
	 end
	 end
	end

Here it is in action:

	run_remotely(ls -l /home/leonardr/dir, example.com, :username=>leonardr,
	 :password => mypass) { |i, o, e| puts o.read }
	# -rw-rw-r-- 1 
leonardr leonardr 33 Dec 29 20:40 file1
	# -rw-rw-r-- 1 leonardr leonardr 102 Dec 29 20:40 file2

Discussion

The Net::SSH library implements a low-level interface to the SSH protocol, but most of the time you don need all that power. You just want to use SSH as a way to spawn and control processes on a remote computer. Thats why Net:SSH also provides a popen3 interface that looks a lot like the popen3 you use to manipulate processes on your own computer.

Apart from the issue of authentication, there are a couple of differences between Net::SSH.popen3 and Open3.popen3. With Open3.popen3, you must be careful to close the standard input stream before reading from the output or error streams. With the Net::SSH version of popen3, you can read from the output or error streams as soon as the process writes any data to it. This lets you interleave stdin writes and stdout reads:

	run_remotely(cat, example.com, :username=>leonardr,
	 :password => mypass) do |stdin, stdout, stderr|
	 stdin.puts Line one.
	 puts stdout.read
	 stdin.puts Line two.
	 puts stdout.read
	end
	# "Line one."
	# "Line two."

Another potential pitfall is that the initial working directory for an SSH session is the filesystem root (/). If youve used the ssh or scp commands, you may be accustomed to starting out in your home directory. To compensate for this, you can change to your home directory within your command: issue a command like cd; ls or cd /home/[user name]/; ls instead of just plain ls.

See Also

  • The Net::SSH manual at: http://net-ssh.rubyforge.org/
  • Recipe 14.2, "Making an HTTPS Web Request," has information on installing the OpenSSL extension that is a prerequisite of ruby-ssh
  • Recipe 14.10, "Being an SSH Client covers the basic rules of SSH"
  • Recipe 20.8, "Driving an External Process with popen," and Recipe 20.9, "Capturing the Output and Error Streams from a Unix Shell Command," cover the basic features of the popen family of methods


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