Being an SSH Client

Problem

You want to securely send data or commands back and forth between your computer, and another computer on which you have a shell account.

Solution

Use the Net::SSH module, which implements the SSH2 protocol. Its found in the net-ssh gem, although some operating systems package it themselves.[2] It lets you implement Ruby applications that work like the familiar ssh and scp.

[2] For instance, its available on Debian GNU/Linux as the package libnet-ssh-ruby1.8.

You can start an SSH session by passing a hostname to Net::SSH::start, along with your shell username and password on that host. If you have an SSH public/private key pair set up between your computer and the remote host, you can omit the username and password:

	require 
ubygems
	require 
et/ssh
	 
Net::SSH.start(example.com, :username=>leonardr,
	 :password=>mypass) do |session|
	 # Manipulate your Net::SSH::Session object here…
	end

Net::SSH::start takes a code block, to which it passes a Net::SSH::Session object. You use the session object to send encrypted data between the machines, or to spawn processes on the remote machine. When the code block ends, the SSH session is automatically terminated.

Discussion

It seems strange now, but until the late 1990s, people routinely used unsecured protocols like telnet to get shell access to remote machines. Remote access was so useful that we were willing to jeopardize our electronic safety by sending our shell passwords (not to mention all the data we looked at) unencrypted across the network. Fortunately, we don have to make that trade-off anymore. The SSH protocol makes it easy to send encrypted traffic between machines, and the client tools ssh and scp have almost completely replaced tools like RSH and nonanonymous FTP.

The Net::SSH library provides a low-level interface to the SSH2 protocol, but most of the time you won need it. Instead, youll use one of the abstractions that make it easy to spawn and control processes on a remote machine. The simplest abstraction is the popen3 method, which works like the local popen3 method in Rubys open3 library. Its covered in more detail in Recipe 20.10, but heres a simple example:

	Net::SSH.start(example.com, :username=>leonardr,
	 :password=>mypass) do |session|
	 cmd = ls -l /home/leonardr/test_dir
	 session.process.popen3(cmd) do |stdin, stdout, stderr|
	 puts stdout.read
	 end
	end
	# -rw-rw-r-- 1 leonardr leonardr 33 Dec 29 20:40 file1
	# -rw-rw-r-- 1 leonardr leonardr 102 Dec 29 20:40 file2

You can run a sequence of commands in a single user shell by calling session.shell.sync:

	Net::SSH.start(example.com, :username=>leonardr,
	 :password=>mypass) do |session|
	 shell = session.shell.sync
	 puts "Original working directory: #{shell.pwd.stdout}"
	 shell.cd 	est_dir
	 puts "Working directory now: #{shell.pwd.stdout}"
	 puts Directory contents:
	 puts shell.ls("-l").stdout
	 shell.exit
	end
	# Original working directory: /home/leonardr
	# Working directory now: /home/leonardr/test_dir
	# Directory contents:
	# -rw-rw-r--1 leonardr leonardr 33 Dec 29 20:40 file1
	# -rw-rw-r--1 leonardr leonardr 102 Dec 29 20:40 file2

The main downside of a synchronized shell is that you usually can pass standard input data into the commands you run. Theres no way to close the standard input stream, so the process will hang forever waiting for more standard input.[3] To pass standard input into a remote process, you should use popen3. With a little trickery, you can control multiple processes simultaneously through your SSH connection; see Recipe 14.11 for details.

[3] The exception is a command like bc, which terminates itself if it sees the line "quit " in its standard input. Commands like cat always look for more standard input.

If your public/private key pair for a host is protected by a passphrase, you will be prompted for the passphrase Net::SSH tries to make a connection to that host. This makes your key more secure, but it will foil your plans to use Net::SSH in an automated script.

You can also use Net::SSH to do TCP/IP port forwarding. As of this writing, you can use it to do X11 forwarding.

See Also

  • Recipe 20.10, "Controlling a Process on Another Machine," covers Net:SSHs implementation of popen3 in more detail. Recipe 14.11 shows how to implement an scp-like service on top of the Net:SSH API, but these three recipes together only scratch the surface of whats possible with Net:SSH. The library manual (http://net-ssh.rubyforge.org/) is comprehensive and easy to read; it covers many topics not touched upon here, like low-level SSH2 operations, callback methods other than on_success, port forwarding, and nonsynchonized user shells
  • Recipe 14.2, "Making an HTTPS Web Request," has information on installing the OpenSSL extension
  • Learn more about public/private keys in the article "OpenSSH key management, Part 1" (http://www-128.ibm.com/developerworks/library/l-keyc.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